[MERGE] mail.message layout

bzr revid: al@openerp.com-20120621225718-8z229a7kieqb9w6q
This commit is contained in:
Antony Lesuisse 2012-06-22 00:57:18 +02:00
commit 725e9da9ed
9 changed files with 549 additions and 221 deletions

View File

@ -271,7 +271,59 @@
<field name="city">Grand-Rosière</field>
<field eval="1367" name="zip"/>
<field name="country_id" ref="base.be"/>
<field name="color">8</field>
</record>
<!-- Some messages linked to the previous opportunity -->
<record id="message_email0" model="mail.message">
<field name="subject">Kitchen design</field>
<field name="model">crm.lead</field>
<field name="res_id" ref="crm_case_rdroundfundingunits25"></field>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[Email0 inquiry]]></field>
<field name="type">email</field>
<field name="state">sent</field>
<field name="user_id" ref="base.user_root"></field>
</record>
<record id="message_note0" model="mail.message">
<field name="subject">Reply</field>
<field name="model">crm.lead</field>
<field name="res_id" ref="crm_case_rdroundfundingunits25"></field>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[Internal note0]]></field>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"></field>
</record>
<record id="message_note0_comment0" model="mail.message">
<field name="subject">Reply</field>
<field name="model">crm.lead</field>
<field name="res_id" ref="crm_case_rdroundfundingunits25"></field>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[comment on note0]]></field>
<field name="parent_id" ref="message_note0"/>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"></field>
</record>
<record id="message_note0_comment1" model="mail.message">
<field name="subject">Reply</field>
<field name="model">crm.lead</field>
<field name="res_id" ref="crm_case_rdroundfundingunits25"></field>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[comment1 on note0]]></field>
<field name="parent_id" ref="message_note0"/>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"></field>
</record>
<record id="message_email1" model="mail.message">
<field name="subject">Your inquiry</field>
<field name="model">crm.lead</field>
<field name="res_id" ref="crm_case_rdroundfundingunits25"></field>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[hello, outgoing email]]></field>
<field name="type">email</field>
<field name="state">received</field>
<field name="user_id" ref="base.user_root"></field>
</record>
<record id="crm_case_unifliege" model="crm.lead">
<field eval="1" name="active"/>
<field name="type">opportunity</field>

View File

@ -91,5 +91,8 @@ The main features are:
'qweb': [
'static/src/xml/mail.xml',
],
'demo': [
'mail_demo.xml',
],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -166,17 +166,17 @@ msgstr ""
#. module: mail
#: view:mail.message:0 field:mail.message,state:0
msgid "State"
msgstr ""
msgstr "État"
#. module: mail
#: view:mail.message:0
msgid "Reply"
msgstr ""
msgstr "Répondre"
#. module: mail
#: view:mail.message:0 selection:mail.message,state:0
msgid "Sent"
msgstr ""
msgstr "Envoyé"
#. module: mail
#: help:mail.compose.message,subtype:0 help:mail.message,subtype:0
@ -514,6 +514,34 @@ msgstr ""
msgid "Preferred response address for the message"
msgstr "Adresse de réponse préférée pour le message"
#. openerp-web
msgid "about a minute ago"
msgstr "il y a une minute"
#. openerp-web
msgid "%d minutes ago"
msgstr "il y a %d minutes"
#. openerp-web
msgid "a day ago"
msgstr "il y a un jour"
#. openerp-web
msgid "%d days ago"
msgstr "il y a %d jours"
#. openerp-web
msgid "a month ago"
msgstr "il y a un mois"
#. openerp-web
msgid "%d months ago"
msgstr "il y a %d mois"
#. openerp-web
msgid "History and Comments"
msgstr "Historique et commentaires"
#~ msgid "Text contents"
#~ msgstr "Contenu du texte"

95
addons/mail/mail_demo.xml Normal file
View File

@ -0,0 +1,95 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="message_blogpost0_attachment0" model="ir.attachment">
<field name="name">A cool attachment</field>
<field name="datas">PT1Tb21lIGNvb2wgYXR0YWNobWVudD09ClByYWVzZW50IHZlbCBtYXNzYSBzZWQgbWFzc2EgY29uc2VxdWF0IGVnZXN0YXMgaW4gdHJpc3RpcXVlIG9yY2ku</field>
<field name="datas_fname">a_cool_attachment</field>
<field name="description"></field>
<field name="res_name">Mail group</field>
<field name="res_model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="type">binary</field>
</record>
<record id="message_blogpost0_attachment1" model="ir.attachment">
<field name="name">Another clean attachment</field>
<field name="datas">PT1Tb21lIGNsZWFuIGF0dGFjaG1lbnQ9PQpOdWxsYSB0dXJwaXMgbGVvLCByaG9uY3VzIHV0IGVnZXN0YXMgc2l0IGFtZXQsIGNvbnNlY3RldHVyIHZpdGFlIHVybmEu</field>
<field name="datas_fname">a_clean_attachment</field>
<field name="description"></field>
<field name="res_name">Mail group</field>
<field name="res_model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="type">binary</field>
</record>
<record id="message_blogpost0" model="mail.message">
<field name="subject">Internal company announce</field>
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[Lorem ipsum dolor <b>sit amet</b>, consectetur <em>adipiscing elit</em>. Pellentesque et quam sapien, in sagittis tellus.
Praesent vel massa sed massa consequat egestas in tristique orci. Praesent iaculis libero et neque vehicula iaculis. Vivamus placerat tincidunt orci ac ornare. Proin ut dolor fringilla velit ultricies consequat. Maecenas sit amet ipsum non leo interdum imperdiet. Donec sapien mi, varius a consequat id, consectetur sit amet nulla.
Fusce tempus elit volutpat mi auctor adipiscing. Nam congue luctus suscipit. Duis vestibulum dapibus enim vitae dignissim. Sed tellus libero, venenatis ut mollis ut, luctus quis dui. Sed rhoncus pulvinar orci in consectetur.
Nulla turpis leo, rhoncus ut egestas sit amet, consectetur vitae urna. Mauris in dolor in sapien tempus vehicula.]]></field>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"/>
<field name="attachment_ids" eval="[(6,0,[ref('message_blogpost0_attachment0'),ref('message_blogpost0_attachment1')])]"/>
</record>
<record id="message_blogpost0_comment0" model="mail.message">
<field name="subject">Reply</field>
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[That was such a <b>tremendous</b> blogpost ! (first comment)]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"/>
</record>
<record id="message_blogpost0_comment1" model="mail.message">
<field name="subject">Reply</field>
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[Agreed !
Would it be possible to learn more about the author ? (second comment)]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"/>
</record>
<record id="message_blogpost0_comment2_attachment0" model="ir.attachment">
<field name="name">Author's full biography</field>
<field name="datas">PT1BYm91dCB0aGUgYXV0aG9yPT0KSW50ZWdlciBzb2RhbGVzIGRvbG9yIGV1IGVsaXQgZnJpbmdpbGxhIGJsYW5kaXQu</field>
<field name="datas_fname">blogpost_author_biography</field>
<field name="description"></field>
<field name="res_name">Mail group</field>
<field name="res_model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="type">binary</field>
</record>
<record id="message_blogpost0_comment2" model="mail.message">
<field name="subject">Reply</field>
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_company"/>
<field name="subtype">html</field>
<field name="body_html"><![CDATA[Sure: Curabitur tempor bibendum diam, et euismod ante rutrum vel.
In quis purus neque. Integer sodales dolor eu elit fringilla blandit. Maecenas lacus nisi, facilisis sit amet viverra eu, tristique vel augue.
Donec viverra congue dui eu blandit. In lacinia molestie nulla, ut sagittis risus feugiat eu.
Check the file in attachment for more information ! (third comment)]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="user_id" ref="base.user_root"/>
<field name="attachment_ids" eval="[(4,ref('message_blogpost0_comment2_attachment0'))]"/>
</record>
</data>
</openerp>

View File

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Group Kanban View !-->
<!-- Group Kanban View !-->
<record model="ir.ui.view" id="view_group_kanban">
<field name="name">mail.group.kanban</field>
<field name="model">mail.group</field>
@ -50,29 +50,30 @@
<field name="type">form</field>
<field name="priority" eval="10"/>
<field name="arch" type="xml">
<form string="Group" version="7.0">
<sheet>
<group colspan="4" col="8">
<group colspan="6" col="4">
<separator string="General Information" colspan="4"/>
<field name="name" colspan="2"/>
<field name="responsible_id" colspan="2"/>
<newline/>
<field name="description" colspan="4"/>
</group>
<group colspan="1" col="2">
<separator string="Group Image" colspan="2"/>
<field name="photo" widget='image' nolabel="1" on_change="onchange_photo(photo)"/>
</group>
<group colspan="1" col="2">
<separator string="Privacy Settings" colspan="2"/>
<field name="public" nolabel="1"/>
<label string="This group is visible by non members" colspan="2"/>
</group>
</group>
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"
options='{"thread_level": 1}'/>
</sheet>
<form string="Group Form" version="7.0">
<div style="padding: 8px">
<div class="oe_right">
<field name="photo" widget='image' on_change="onchange_photo(photo)"/>
</div>
<div class="oe_title">
<div class="oe_edit_only">
<label for="name"/>
</div>
<h1><field name="name"/></h1>
<div class="oe_edit_only">
<label for="responsible_id"/>
</div>
<field name="responsible_id" class="oe_inline"/>
<div class="oe_edit_only">
<label for="public"/>
<field name="public" class="oe_inline"/>
</div>
<field name="description" colspan="4" nolabel="1"/>
</div>
</div>
<footer>
<field name="message_ids" colspan="4" widget="ThreadView" options='{"thread_level": 1}'/>
</footer>
</form>
</field>
</record>

View File

@ -413,7 +413,30 @@ class mail_thread(osv.osv):
""" OpenChatter feature: return thread messages
"""
msg_ids = self.message_load_ids(cr, uid, ids, limit, offset, domain, ascent, root_ids, context=context)
msgs = self.pool.get('mail.message').read(cr, uid, msg_ids, context=context)
msgs = self.pool.get('mail.message').read(cr, uid, msg_ids, [], context=context)
""" Retrieve all attachments names """
map_id_to_name = {}
for msg in msgs:
for attach_id in msg["attachment_ids"]:
map_id_to_name[attach_id] = '' # use empty string as a placeholder
ids = map_id_to_name.keys()
names = self.pool.get('ir.attachment').name_get(cr, uid, ids, context=context)
# convert the list of tuples into a dictionnary
for name in names:
map_id_to_name[name[0]] = name[1]
# give corresponding ids and names to each message
for msg in msgs:
msg["attachments"] = []
for attach_id in msg["attachment_ids"]:
msg["attachments"].append({'id': attach_id, 'name': map_id_to_name[attach_id]})
""" Sort and return messages """
msgs = sorted(msgs, key=lambda d: (-d['id']))
return msgs

View File

@ -9,35 +9,19 @@
background: white;
}
.openerp div.oe_mail_wall_act {
.openerp div.oe_mail_wall_action {
padding: 8px;
background: #eee;
border: 1px solid #ccc;
}
.openerp div.oe_mail_wall_act:after {
.openerp div.oe_mail_wall_action:after {
content: "";
display: block;
clear: both;
}
/* 2 columns view */
.openerp div.oe_mail_wall_left {
float: left;
width: 560px;
margin: 8px;
}
.openerp div.oe_mail_wall_right {
margin-left: 565px;
margin: 8px;
}
.openerp div.oe_mail_wall_threads {
margin-top: 8px;
}
.openerp textarea.oe_mail_wall_action_textarea {
.openerp .oe_mail_wall_action textarea {
width: 474px;
height: 60px;
padding: 4px;
@ -45,24 +29,41 @@
float: right;
}
.openerp div.oe_mail_wall_threads textarea {
/* 2 columns view */
.openerp div.oe_mail_wall_main {
float: left;
width: 560px;
margin: 8px;
}
.openerp div.oe_mail_wall_aside {
margin-left: 565px;
margin: 8px;
}
/* Threads */
.openerp .oe_mail_wall_threads {
margin-top: 8px;
}
.openerp .oe_mail_wall_threads textarea {
height: 40px;
padding: 4px;
}
.openerp .oe_mail_wall_thread:first .oe_mail_msg_notification {
border-top: 0;
}
.openerp div.oe_mail_thread_subthread img {
width: 28px;
height: 28px;
}
.openerp div.oe_mail_msg_content {
position: relative;
width: 486px;
}
.openerp div.oe_mail_msg_content p {
margin: 4px 0;
}
.openerp div.oe_mail_msg_content li{
float: left;
margin-right: 3px;
@ -152,14 +153,14 @@
/* ThreadDisplay */
/* ------------------------------ */
.openerp div.oe_mail_thread_act {
.openerp div.oe_mail_thread_action {
white-space: normal;
padding: 8px;
background: #eee;
border-top: 1px solid #ccc
border-top: 1px solid #ccc;
}
.openerp div.oe_mail_thread_act:after {
.openerp div.oe_mail_thread_action:after {
content: "";
display: block;
clear: both;
@ -173,7 +174,7 @@
margin-left: 66px;
}
.openerp div.oe_mail_thread_subthread li.oe_mail_thread_msg:last-child {
.openerp div.oe_mail_thread_subthread .oe_mail_thread_msg:last-child {
margin-bottom: 8px;
}
@ -182,25 +183,29 @@
border-bottom: 1px solid #D2D9E7;
}
.openerp li.oe_mail_thread_msg:after {
.openerp .oe_mail_thread_msg:after {
content: "";
display: block;
clear: both;
}
.openerp li.oe_mail_thread_msg > div:after {
.openerp .oe_mail_thread_msg > div:after {
content: "";
display: block;
clear: both;
}
.openerp .oe_mail_msg_notification, .openerp .oe_mail_msg_comment, .openerp .oe_mail_msg_email {
.openerp .oe_mail_msg_notification,
.openerp .oe_mail_msg_comment,
.openerp .oe_mail_msg_email {
padding: 8px;
}
.openerp .oe_mail_msg_comment, .openerp .oe_mail_msg_email, .openerp .oe_mail_msg_notification {
.openerp .oe_mail_msg_comment,
.openerp .oe_mail_msg_email,
.openerp .oe_mail_msg_notification {
background: white;
border-top: 1px solid #ccc
border-top: 1px solid #ccc;
}
.openerp .oe_email_icon {
@ -212,7 +217,9 @@
background: #eee;
}
.openerp .oe_mail_msg_notification:after, .openerp .oe_mail_msg_comment:after, .openerp .oe_mail_msg_email:after {
.openerp .oe_mail_msg_notification:after,
.openerp .oe_mail_msg_comment:after,
.openerp .oe_mail_msg_email:after {
content: "";
display: block;
clear: both;
@ -249,15 +256,6 @@
/* Styling (should be openerp) */
/* ------------------------------ */
.openerp ul.oe_mail {
padding: 0;
margin: 0;
}
.openerp li.oe_mail {
list-style-type: none;
}
.openerp input.oe_mail, textarea.oe_mail {
width: 432px;
padding: 4px;
@ -284,20 +282,115 @@
-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
}
.openerp p.oe_mail_msg {
.openerp div.oe_mail_msg {
padding: 0;
margin: 0 0 4px 0;
}
.openerp a.oe_mail_oe_intlink {
color: #8786b7;
}
.openerp .oe_mail_oe_bold {
font-weight: bold;
}
/*.openerp .oe_mail_oe_space:after {*/
/*content: " · ";*/
/*margin-right: 2px;*/
/*}*/
/* ------------------------------ */
/* Messages layout */
/* ------------------------------ */
.openerp .oe_mail_msg .oe_mail_msg_title {
margin: 0;
font-size: 1.3em;
font-weight: bold;
}
.openerp .oe_mail_msg .oe_mail_msg_title a:link,
.openerp .oe_mail_msg .oe_mail_msg_title a:visited {
color: #4C4C4C;
text-decoration: none;
}
.openerp .oe_mail_msg_subtitle {
margin: 0 0 .5em 0;
}
.openerp .oe_mail_msg_footer,
.openerp .oe_mail_msg_subtitle {
color: #888;
}
.openerp .oe_mail_msg_body,
.openerp .oe_mail_msg_body_short {
margin-bottom: .5em;
text-align: justify;
}
/* Read more/less link */
.openerp .oe_mail_msg_content .expand,
.openerp .oe_mail_msg_content .reduce {
font-weight: bold;
}
/* Dropdown menu */
.openerp .oe_mail_msg_content .oe_dropdown_toggle {
position: absolute;
top: 0px;
right: 3px;
}
.openerp .oe_mail_msg_content .oe_dropdown_arrow:after {
border-top: 4px solid transparent;
}
.openerp .oe_mail_msg_content:hover .oe_dropdown_arrow:after {
border-top: 4px solid #404040;
}
.openerp .oe_mail_msg_footer li:after {
content: " · ";
}
.openerp .oe_mail_msg_footer li:last-child:after {
content: "";
}
/* Attachments list */
.openerp ul.oe_mail_msg_attachments {
display: none;
width: 100%;
border-top: 1px solid #CCC;
margin: .5em 0 0 0;
padding: .5em 0;
list-style-position: inside;
}
.openerp ul.oe_mail_msg_attachments li {
float: none;
margin: 0;
padding: 0;
list-style-type: square;
}
/* ------------------------------ */
/* Group Form */
/* ------------------------------ */
div.oe_mail_group_advanced_details {
display: none;
}
.oe_form_sheetbg.openerp_mail_group_sheet {
min-height: 0px;
max-height: none;
}
.oe_form_sheetbg.openerp_mail_group_sheet .oe_form_sheet {
min-height: 0px;
max-height: none;
padding: 0px 18px;
max-width: 80%;
}
/* Resize group logo */
.oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_image > img {
max-width: 100px;
max-height: 100px;
}
/* Resize group description */
.oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea {
height: 40px;
}

View File

@ -1,25 +1,25 @@
openerp.mail = function(session) {
var _t = session.web._t,
_lt = session.web._lt;
var mail = session.mail = {};
/**
* Add records to sorted_comments array
* @param {Array} records records from mail.message sorted by date desc
* @returns {Object} cs comments_structure: dict
* cs.model_to_root_ids = {model: [root_ids], }
* cs.new_root_ids = [new_root_ids]
* cs.root_ids = [root_ids]
* cs.msgs = {record.id: record,}
* cs.tree_struct = {record.id: {
* 'level': record_level in hierarchy, 0 is root,
* 'msg_nbr': number of childs,
* 'direct_childs': [msg_ids],
* 'all_childs': [msg_ids],
* 'for_thread_msgs': [records],
* 'ancestors': [msg_ids], } }
*/
* Add records to sorted_comments array
* @param {Array} records records from mail.message sorted by date desc
* @returns {Object} cs comments_structure: dict
* cs.model_to_root_ids = {model: [root_ids], }
* cs.new_root_ids = [new_root_ids]
* cs.root_ids = [root_ids]
* cs.msgs = {record.id: record,}
* cs.tree_struct = {record.id: {
* 'level': record_level in hierarchy, 0 is root,
* 'msg_nbr': number of childs,
* 'direct_childs': [msg_ids],
* 'all_childs': [msg_ids],
* 'for_thread_msgs': [records],
* 'ancestors': [msg_ids], } }
*/
function tools_sort_comments(cs, records, parent_id) {
var cur_iter = 0; var max_iter = 10; var modif = true;
while ( modif && (cur_iter++) < max_iter) {
@ -59,8 +59,6 @@ openerp.mail = function(session) {
/* Add ThreadDisplay widget to registry */
session.web.form.widgets.add( 'Thread', 'openerp.mail.Thread');
// session.web.page.readonly.add( 'Thread', 'openerp.mail.Thread');
/**
* ThreadDisplay widget: this widget handles the display of a thread of
* messages. The [thread_level] parameter sets the thread level number:
@ -72,7 +70,7 @@ openerp.mail = function(session) {
* either it will fetch [limit] messages related to [res_model]:[res_id].
*/
mail.Thread = session.web.Widget.extend({
template: 'Thread',
template: 'mail.Thread',
/**
* @param {Object} parent parent
@ -117,15 +115,24 @@ openerp.mail = function(session) {
},
start: function() {
var self = this;
this._super.apply(this, arguments);
// customize display
if (! this.display.show_post_comment) this.$element.find('div.oe_mail_thread_act').hide();
if (! this.display.show_post_comment) {
this.$element.find('div.oe_mail_thread_action').hide();
}
// add events
this.add_events();
/* display user, fetch comments */
// display user, fetch comments
this.display_current_user();
if (this.params.records) var display_done = this.display_comments_from_parameters(this.params.records);
else var display_done = this.init_comments();
if (this.params.records) {
var display_done = this.display_comments_from_parameters(this.params.records);
} else {
var display_done = this.init_comments();
}
return display_done
},
@ -143,7 +150,7 @@ openerp.mail = function(session) {
});
// event: click on 'reply' in msg
this.$element.find('div.oe_mail_thread_display').delegate('a.oe_mail_msg_reply', 'click', function (event) {
var act_dom = $(this).parents('div.oe_mail_thread_display').find('div.oe_mail_thread_act:first');
var act_dom = $(this).parents('div.oe_mail_thread_display').find('div.oe_mail_thread_action:first');
act_dom.toggle();
event.preventDefault();
});
@ -154,9 +161,9 @@ openerp.mail = function(session) {
var msg_id = event.srcElement.dataset.id;
if (! msg_id) return false;
var call_defer = self.ds_msg.unlink([parseInt(msg_id)]);
$(event.srcElement).parents('li.oe_mail_thread_msg').eq(0).hide();
$(event.srcElement).parents('.oe_mail_thread_msg').eq(0).hide();
if (self.params.thread_level > 0) {
$(event.srcElement).parents('ul.oe_mail_thread').eq(0).hide();
$(event.srcElement).parents('.oe_mail_thread').eq(0).hide();
}
return false;
});
@ -168,14 +175,14 @@ openerp.mail = function(session) {
if (! msg_id) return false;
//console.log(msg_id);
var call_defer = self.ds.call('message_remove_pushed_notifications', [[self.params.res_id], [parseInt(msg_id)], true]);
$(event.srcElement).parents('li.oe_mail_thread_msg').eq(0).hide();
$(event.srcElement).parents('.oe_mail_thread_msg').eq(0).hide();
if (self.params.thread_level > 0) {
$(event.srcElement).parents('ul.oe_mail_thread').eq(0).hide();
$(event.srcElement).parents('.oe_mail_thread').eq(0).hide();
}
return false;
});
// event: click on an internal link
this.$element.find('div.oe_mail_thread_display').delegate('a.intlink', 'click', function (event) {
this.$element.find('div.oe_mail_thread_display').delegate('a.oe_mail_internal_link', 'click', function (event) {
// lazy implementation: fetch data and try to redirect
if (! event.srcElement.dataset.resModel) return false;
else var res_model = event.srcElement.dataset.resModel;
@ -193,6 +200,12 @@ openerp.mail = function(session) {
}
else self.do_action({ type: 'ir.actions.act_window', res_model: res_model, res_id: parseInt(res_id), views: [[false, 'form']]});
});
// event: click on 'attachment(s)' in msg
this.$element.delegate('a.oe_mail_msg_view_attachments', 'click', function (event) {
var act_dom = $(this).parent().parent().parent().find('.oe_mail_msg_attachments');
act_dom.toggle();
return false;
});
},
destroy: function () {
@ -215,10 +228,23 @@ openerp.mail = function(session) {
$.when(defer).then(function (records) {
if (records.length <= self.params.limit) self.display.show_more = false;
else { self.display.show_more = true; records.pop(); }
//build attachments download urls and compute time-relative from dates
for (var k in records) {
records[k].timerelative = $.timeago(records[k].date);
if (records[k].attachments) {
for (var l in records[k].attachments) {
records[k].attachments[l].url = self.session.origin + '/web/binary/saveas?session_id=' + self.session.session_id + '&model=ir.attachment&field=datas&filename_field=datas_fname&id='+records[k].attachments[l].id;
}
}
}
self.display_comments(records);
if (self.display.show_more == true) self.$element.find('div.oe_mail_thread_more:last').show();
else self.$element.find('div.oe_mail_thread_more:last').hide();
});
});
return defer;
},
@ -253,7 +279,7 @@ openerp.mail = function(session) {
self.display_comment(record);
self.thread = new mail.Thread(self, {'res_model': self.params.res_model, 'res_id': self.params.res_id, 'uid': self.params.uid,
'records': sub_msgs, 'thread_level': (self.params.thread_level-1), 'parent_id': record.id});
self.$element.find('li.oe_mail_thread_msg:last').append('<div class="oe_mail_thread_subthread"/>');
self.$element.find('.oe_mail_thread_msg:last').append('<div class="oe_mail_thread_subthread"/>');
self.thread.appendTo(self.$element.find('div.oe_mail_thread_subthread:last'));
}
else if (self.params.thread_level == 0) {
@ -268,8 +294,12 @@ openerp.mail = function(session) {
* Display a record
*/
display_comment: function (record) {
if (record.type == 'email') { record.mini_url = ('/mail/static/src/img/email_icon.png'); }
else { record.mini_url = this.thread_get_avatar('res.users', 'avatar', record.user_id[0]); }
record.body = this.do_text_nl2br(record.body, true);
if (record.type == 'email') {
record.mini_url = ('/mail/static/src/img/email_icon.png');
} else {
record.mini_url = this.thread_get_avatar('res.users', 'avatar', record.user_id[0]);
}
// body text manipulation
record.body = this.do_clean_text(record.body);
record.tr_body = this.do_truncate_string(record.body, this.params.msg_more_limit);
@ -278,14 +308,15 @@ openerp.mail = function(session) {
// format date according to the user timezone
record.date = session.web.format_value(record.date, {type:"datetime"});
// render
$(session.web.qweb.render('ThreadMsg', {'record': record, 'thread': this, 'params': this.params, 'display': this.display})
).appendTo(this.$element.children('div.oe_mail_thread_display:first'));
// OPTIONS
var rendered = session.web.qweb.render('mail.Thread.message', {'record': record, 'thread': this, 'params': this.params, 'display': this.display});
$( rendered).appendTo(this.$element.children('div.oe_mail_thread_display:first'));
// truncated: hide full-text, show summary, add buttons
if (record.tr_body) {
var node_body = this.$element.find('span.oe_mail_msg_body:last').append(' <a href="#" class="reduce">[ ... Show less]</a>');
var node_body_short = this.$element.find('span.oe_mail_msg_body_short:last').append(' <a href="#" class="expand">[ ... Show more]</a>');
var node_body = this.$element.find('.oe_mail_msg_body:last');
var node_body_short = this.$element.find('.oe_mail_msg_body_short:last').append('... <a href="#" class="expand">See more</a>');
node_body.hide();
node_body.find('a:last').click(function() { node_body.hide(); node_body_short.show(); return false; });
node_body_short.find('a:last').click(function() { node_body_short.hide(); node_body.show(); return false; });
}
},
@ -403,7 +434,7 @@ openerp.mail = function(session) {
var regex_res = regex_login.exec(string);
while (regex_res != null) {
var login = regex_res[2];
string = string.replace(regex_res[0], regex_res[1] + '<a href="#" class="intlink oe_mail_oe_intlink" data-res-model="res.users" data-res-login = ' + login + '>@' + login + '</a>');
string = string.replace(regex_res[0], regex_res[1] + '<a href="#" class="oe_mail_internal_link" data-res-model="res.users" data-res-login = ' + login + '>@' + login + '</a>');
regex_res = regex_login.exec(string);
}
/* special shortcut: :name, try to find an icon if in list */
@ -422,16 +453,32 @@ openerp.mail = function(session) {
return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || '');
},
/**
* @param {String} string to truncate
* @param {Number} max number of chars to display
* @returns {String} truncated string
*/
do_truncate_string: function(string, max_length) {
if (string.length <= (max_length * 1.2)) return false;
else return string.slice(0, max_length);
// multiply by 1.2: prevent truncating an just too little long string
if (string.length <= (max_length * 1.2)) {
return false;
} else {
return string.slice(0, max_length);
}
},
/** Removes html tags, except b, em, br */
do_clean_text: function (string) {
var html = $('<div/>').text(string.replace(/\s+/g, ' ')).html().replace(new RegExp('&lt;(/)?(b|em)\\s*&gt;', 'gi'), '<$1$2>');
var html = $('<div/>').text(string.replace(/\s+/g, ' ')).html().replace(new RegExp('&lt;(/)?(b|em|br|br /)\\s*&gt;', 'gi'), '<$1$2>');
return html;
},
/** Replaces line bracks by html line breaks (br) */
do_text_nl2br: function (str, is_xhtml) {
var break_tag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ break_tag +'$2');
},
/**
*
* var regex_login = new RegExp(/(^|\s)@((\w|@|\.)*)/g);
@ -466,15 +513,11 @@ openerp.mail = function(session) {
});
/* Add ThreadView widget to registry */
session.web.form.widgets.add( 'ThreadView', 'openerp.mail.RecordThread');
// session.web.page.readonly.add( 'ThreadView', 'openerp.mail.RecordThread');
/* ThreadView widget: thread of comments */
mail.RecordThread = session.web.form.AbstractField.extend({
// QWeb template to use when rendering the object
template: 'RecordThread',
template: 'mail.RecordThread',
init: function() {
this._super.apply(this, arguments);
@ -516,7 +559,7 @@ openerp.mail = function(session) {
this._super.apply(this, arguments);
var self = this;
this.reinit();
if (! this.view.datarecord.id) { this.$element.find('ul.oe_mail_thread').hide(); return; }
if (! this.view.datarecord.id) { this.$element.find('.oe_mail_thread').hide(); return; }
// fetch followers
var fetch_sub_done = this.fetch_subscribers();
// create and render Thread widget
@ -541,7 +584,7 @@ openerp.mail = function(session) {
if (record.id == self.session.uid) { self.is_subscriber = true; }
var mini_url = self.thread_get_avatar('res.users', 'avatar', record.id);
$('<li><img class="oe_mail_oe_left oe_mail_msg_image" src="' + mini_url + '"/>' +
'<a href="#" class="intlink oe_mail_oe_intlink" data-res-model="res.users" data-res-id="' + record.id + '">' + record.name + '</a></li>').appendTo(user_list);
'<a href="#" class="oe_mail_internal_link" data-res-model="res.users" data-res-id="' + record.id + '">' + record.name + '</a></li>').appendTo(user_list);
});
if (self.is_subscriber) {
self.$element.find('button.oe_mail_button_follow').hide();
@ -573,14 +616,13 @@ openerp.mail = function(session) {
return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || '');
},
});
/* Add WallView widget to registry */
session.web.client_actions.add('mail.all_feeds', 'session.mail.WallView');
/* WallView widget: a wall of messages */
mail.WallView = session.web.Widget.extend({
template: 'Wall',
template: 'mail.Wall',
/**
* @param {Object} parent parent
@ -630,7 +672,7 @@ openerp.mail = function(session) {
add_event_handlers: function () {
var self = this;
// post a comment
this.$element.find('button.oe_mail_wall_button_comment').click(function () { return self.do_comment(); });
this.$element.find('.oe_mail_wall_action button').click(function () { return self.do_comment(); });
// display more threads
this.$element.find('button.oe_mail_wall_button_more').click(function () { return self.do_more(); });
},
@ -684,7 +726,7 @@ openerp.mail = function(session) {
this.search['context'] = _.extend(this.params.context, this.search_results.context);
this.display_show_more = true;
this.comments_structure = {'root_ids': [], 'new_root_ids': [], 'msgs': {}, 'tree_struct': {}, 'model_to_root_ids': {}};
this.$element.find('div.oe_mail_wall_threads').empty();
this.$element.find('ul.oe_mail_wall_threads').empty();
return this.fetch_comments(this.params.limit, 0);
},
@ -716,14 +758,14 @@ openerp.mail = function(session) {
var records = self.comments_structure.tree_struct[root_id]['for_thread_msgs'];
var model_name = self.comments_structure.msgs[root_id]['model'];
var res_id = self.comments_structure.msgs[root_id]['res_id'];
var render_res = session.web.qweb.render('WallThreadContainer', {});
$('<div class="oe_mail_wall_thread">').html(render_res).appendTo(self.$element.find('div.oe_mail_wall_threads'));
var render_res = session.web.qweb.render('mail.WallThreadContainer', {});
$('<li class="oe_mail_wall_thread">').html(render_res).appendTo(self.$element.find('ul.oe_mail_wall_threads'));
var thread = new mail.Thread(self, {
'res_model': model_name, 'res_id': res_id, 'uid': self.session.uid, 'records': records,
'parent_id': false, 'thread_level': self.params.thread_level, 'show_hide': true}
);
self.thread_list.push(thread);
return thread.appendTo(self.$element.find('div.oe_mail_wall_thread:last'));
return thread.appendTo(self.$element.find('li.oe_mail_wall_thread:last'));
});
// update TODO
this.comments_structure['root_ids'] = _.union(this.comments_structure['root_ids'], this.comments_structure['new_root_ids']);
@ -770,12 +812,13 @@ openerp.mail = function(session) {
/** Action: Posts a comment */
do_comment: function () {
var comment_node = this.$element.find('textarea.oe_mail_wall_action_textarea');
var comment_node = this.$element.find('.oe_mail_wall_action textarea');
var body_text = comment_node.val();
comment_node.val('');
var call_done = this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, false, 'comment', 'html']).then(this.proxy('init_and_fetch_comments'));
},
});
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:

View File

@ -1,36 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<div t-name="Wall" class="oe_mail_wall">
<div t-name="mail.Wall" class="oe_mail_wall">
<table class="oe_view_manager_header">
<tr class="oe_header_row">
<td><h2 class="oe_view_title">All Feeds</h2></td>
<td><div class="oe_view_manager_view_search" t-opentag="true"/></td>
</tr>
</table>
<div class="oe_mail_wall_left">
<div class="oe_mail_wall_act">
<div class="oe_mail_wall_main">
<div class="oe_mail_wall_action">
<img class="oe_mail_msg_image oe_left" alt="User img"/>
<textarea class="oe_mail oe_mail_wall_action_textarea" placeholder="What are you working on?"/>
<button class="oe_right oe_mail_wall_button_comment" type="button">Post comment</button>
</div>
<div class="oe_clear"></div>
<div class="oe_mail_wall_threads">
</div>
<ul class="oe_mail_wall_threads">
</ul>
<div class="oe_mail_wall_more">
<button class="oe_mail_wall_button_more" type="button">See more discussions</button>
</div>
</div>
<div class="oe_mail_wall_right"></div>
<div class="oe_mail_wall_aside"></div>
</div>
<t t-name="WallThreadContainer">
<t t-name="mail.WallThreadContainer">
</t>
<div t-name="RecordThread" class="oe_mail_recthread">
<h4>History and Comments</h4>
<div class="oe_mail_recthread_left">
</div>
<div t-name="mail.RecordThread" class="oe_mail_recthread">
<div class="oe_mail_recthread_left"></div>
<div class="oe_mail_recthread_right">
<div class="oe_mail_recthread_actions">
<button type="button" class="oe_mail_button_follow oe_mail_button_mouseout">Not following</button>
@ -44,8 +42,8 @@
</div>
</div>
<ul t-name="Thread" class="oe_mail oe_mail_thread">
<div class="oe_mail_thread_act">
<div t-name="mail.Thread" class="oe_mail oe_mail_thread">
<div class="oe_mail_thread_action">
<img class="oe_mail_msg_image oe_left" alt="User img"/>
<div class="oe_mail_msg_content">
<textarea class="oe_mail oe_mail_action_textarea" placeholder="Add your comment here..." onfocus="this.value = '';"/>
@ -55,78 +53,70 @@
<div class="oe_mail_thread_more">
<button class="oe_mail_button_more" type="button">Load more messages</button>
</div>
</ul>
</div>
<li t-name="ThreadMsg" t-attf-class="oe_mail oe_mail_thread_msg">
<!-- default layout -->
<div t-name="mail.Thread.message" class="oe_mail oe_mail_thread_msg">
<div t-attf-class="oe_mail_msg_#{record.type}">
<img t-if="record.type == 'email'" class="oe_email_icon oe_left" src="/mail/static/src/img/email_icon.png"/>
<img t-if="record.type == 'notification' || record.type == 'comment'" class="oe_mail_msg_image oe_left" t-att-src="record.mini_url"/>
<img class="oe_email_icon oe_left" t-att-src="record.mini_url"/>
<div class="oe_mail_msg_content">
<t t-if="record.type == 'email'"><t t-call="EmailDisplay" /></t>
<t t-if="record.type == 'notification' || record.type == 'comment'"><t t-call="NoteDisplay" /></t>
</div>
<t t-if="record.type == 'tmp'"><t t-call="ThreadDisplay" /></t>
</div>
</li>
<t t-name="NoteDisplay">
<p class="oe_mail_msg">
<t t-if="params.thread_level > 0">
<a href="#" class="intlink oe_mail_oe_intlink" t-attf-data-res-model='{params.res_model}' t-attf-data-res-id='{params.res_id}'><t t-raw="record.record_name"/></a>
</t>
<span class="oe_mail_msg_body"><t t-raw="record.body"/></span>
<t t-if="record.tr_body"><span class="oe_mail_msg_body_short"><t t-raw="record.tr_body"/></span></t><br/>
<ul>
<t t-if="display['show_reply']">
<li><a href="#" class="oe_mail_msg_reply oe_mail_oe_intlink">Reply</a><span class="oe_mail_oe_space oe_fade"> · </span></li>
</t>
<t t-if="display['show_delete']">
<t t-if="thread._is_author(record.user_id[0])">
<li><a href="#" t-attf-data-id='{record.id}' class="oe_mail_msg_delete oe_mail_oe_intlink">Delete</a><span class="oe_mail_oe_space oe_fade"> · </span></li>
</t>
</t>
<t t-if="display['show_hide']">
<t t-if="!(thread._is_author(record.user_id[0]))">
<li><a href="#" t-attf-data-id='{record.id}' class="oe_mail_msg_hide oe_mail_oe_intlink">Hide</a><span class="oe_mail_oe_space oe_fade"> · </span></li>
</t>
</t>
<li>
<span class="oe_fade"><t t-raw="record.date"/>
by <a href="#" class="intlink oe_mail_oe_intlink" data-res-model='res.users' t-attf-data-res-id='{record.user_id[0]}'><t t-raw="record.user_id[1]"/></a>
<span class="oe_dropdown_toggle oe_dropdown_arrow">
<ul class="oe_dropdown_menu">
<t t-if="thread._is_author(record.user_id[0]) &amp;&amp; display['show_delete']">
<li><a href="#" t-attf-data-id='{record.id}' class="oe_mail_msg_delete">Delete</a></li>
</t>
<t t-if="!thread._is_author(record.user_id[0]) &amp;&amp; display['show_hide']">
<li><a href="#" t-attf-data-id='{record.id}' class="oe_mail_msg_hide">Hide</a></li>
</t>
</ul>
</span>
</li>
</ul>
</p>
</t>
<t t-name="EmailDisplay">
<p class="oe_mail_msg oe_mail_msg_p_email_header">
<t t-if="params.thread_level > 0">
<a href="#" class="intlink oe_mail_oe_intlink" t-attf-data-res-model='{params.res_model}' t-attf-data-res-id='{params.res_id}'><t t-raw="record.record_name"/></a>
</t>
</p>
<p><span class="oe_mail_oe_bold">From:</span> <t t-esc="record.email_from"/></p>
<p><span class="oe_mail_oe_bold">Subject:</span> <t t-esc="record.subject"/></p>
<p class="oe_mail_msg">
<span class="oe_mail_msg_body"><t t-raw="record.body"/></span>
<t t-if="record.tr_body"><span class="oe_mail_msg_body_short"><t t-raw="record.tr_body"/></span></t>
</p>
<div class="oe_mail_msg">
<t t-if="record.subject">
<h1 class="oe_mail_msg_title">
<a href="#" class="oe_mail_internal_link"><t t-raw="record.subject"/></a>
</h1>
</t>
<p class="oe_mail_msg_subtitle">
<t t-if="params.thread_level > 0">
<a href="#" t-attf-data-res-model='{params.res_model}' t-attf-data-res-id='{params.res_id}' class="oe_mail_internal_link"><t t-raw="record.record_name"/></a>
</t>
<span class="oe_mail_msg_author"><a href="#" data-res-model='res.users' t-attf-data-res-id='{record.user_id[0]}' class="oe_mail_internal_link"><t t-raw="record.user_id[1]"/></a></span>
<span class="oe_mail_msg_date" t-att-title="record.date"><t t-raw="record.timerelative"/></span>
</p>
<div class="oe_mail_msg_body"><t t-raw="record.body"/></div>
<t t-if="record.tr_body">
<div class="oe_mail_msg_body_short"><t t-raw="record.tr_body"/></div>
</t>
<ul class="oe_mail_msg_footer">
<t t-if="display['show_reply']">
<li><a href="#" class="oe_mail_msg_reply">Reply</a></li>
</t>
<li><a href="#">Like</a></li>
<t t-if="record.attachment_ids.length > 0">
<li>
<a href="#" class="oe_mail_msg_view_attachments">
<t t-if="record.attachment_ids.length == 1">Attachment</t>
<t t-if="record.attachment_ids.length > 1">Attachments (<t t-raw="record.attachment_ids.length"/>)</t>
</a>
</li>
</t>
</ul>
<t t-if="record.attachment_ids.length > 0">
<div class="oe_clear"></div>
<ul class="oe_mail_msg_attachments">
<t t-foreach="record.attachments" t-as="attachment">
<li> <a t-att-href="attachment.url"><t t-raw="attachment.name"/></a> </li>
</t>
</ul>
</t>
</div>
</div>
</div>
</div>
<ul>
<t t-if="display['show_delete']">
<t t-if="thread._is_author(record.user_id[0])">
<li><a href="#" t-attf-data-id='{record.id}' class="oe_mail_msg_delete oe_mail_oe_intlink">Delete</a><span class="oe_mail_oe_space oe_fade"> · </span></li>
</t>
</t>
<t t-if="display['show_hide']">
<t t-if="!(thread._is_author(record.user_id[0]))">
<li><a href="#" t-attf-data-id='{record.id}' class="oe_mail_msg_hide oe_mail_oe_intlink">Hide</a><span class="oe_mail_oe_space oe_fade"> · </span></li>
</t>
</t>
<li>
<span class="oe_fade"><t t-raw="record.date"/></span>
</li>
</ul>
</t>
</template>