summaryrefslogtreecommitdiff
path: root/addons/mail/static/src
diff options
context:
space:
mode:
authorThibault Delavallée <tde@openerp.com>2012-12-21 17:34:59 +0100
committerThibault Delavallée <tde@openerp.com>2012-12-21 17:34:59 +0100
commitf6894591a3e1a5bcd38ad58c8d522e7aefea798a (patch)
tree7e2b4ce59e6c80ff088b6c303225832ecf2f3f17 /addons/mail/static/src
parent912533f1f3e3ef69792d7b373a9584eaadd987d7 (diff)
parentdcd9f1d35e2e898cf7835b88d7adbbb7646cbc66 (diff)
[MERGE] mail: varioux fixes and improvements.
Mail: - Chatter widget now checks email address in a given thread that are not linked to any partner; it proposes to create a partner that will be added as follower to the document for each found email address - fixed reload of a posted message - invite wizard now uses the many2many_tags_email widget, to avoid sending invitations to partners not having an email address defined Misc : - note: fixed padding of note leading to ugly display of notes bzr revid: tde@openerp.com-20121221163459-wv0jiss4wplla1yl
Diffstat (limited to 'addons/mail/static/src')
-rw-r--r--addons/mail/static/src/css/mail.css25
-rw-r--r--addons/mail/static/src/js/mail.js157
-rw-r--r--addons/mail/static/src/js/mail_followers.js103
-rw-r--r--addons/mail/static/src/xml/mail.xml27
-rw-r--r--addons/mail/static/src/xml/mail_followers.xml7
5 files changed, 233 insertions, 86 deletions
diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css
index e154e285f39..54f97f448f4 100644
--- a/addons/mail/static/src/css/mail.css
+++ b/addons/mail/static/src/css/mail.css
@@ -253,6 +253,19 @@
.openerp .oe_mail .oe_msg_composer .oe_msg_attachment_list{
display: block;
}
+.openerp .oe_mail .oe_msg_composer .oe_emails_from{
+ font-size: 12px;
+ margin-left: 20px;
+ margin-bottom: 2px;
+}
+.openerp .oe_mail .oe_msg_composer .oe_emails_from label{
+ vertical-align: middle;
+ display: block;
+ line-height: 14px;
+}
+.openerp .oe_mail .oe_msg_composer .oe_emails_from input{
+ vertical-align: middle;
+}
.openerp .oe_mail .oe_attachment{
display: inline-block;
width: 100px;
@@ -465,8 +478,8 @@
}
.openerp .oe_mail .oe_msg_content .oe_mail_list_recipients{
font-size: 12px;
- margin-top: 4px;
- margin-bottom: 4px;
+ margin: 4px 0 4px 20px;
+ text-indent: -20px;
}
/* ---------------- HIDDEN MESSAGES ------------------ */
@@ -578,6 +591,14 @@
margin-right:4px;
border-radius: 2px;
}
+.openerp .oe_followers .oe_remove_follower{
+ cursor: pointer;
+ float: right;
+}
+
+.openerp .oe_followers .oe_show_more{
+ cursor: pointer;
+}
/* ---------------- MESSAGES BODY ------------------ */
.openerp .oe_mail .oe_msg_content .oe_blockquote,
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index 03d13a5605b..29a2e076b19 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -369,6 +369,7 @@ openerp.mail = function (session) {
this._super(parent, datasets, options);
this.show_compact_message = false;
this.show_delete_attachment = true;
+ this.emails_from = [];
},
start: function () {
@@ -478,9 +479,11 @@ openerp.mail = function (session) {
this.$('.oe_cancel').on('click', _.bind( this.on_cancel, this) );
this.$('.oe_post').on('click', _.bind( this.on_message_post, this) );
this.$('.oe_full').on('click', _.bind( this.on_compose_fullmail, this, this.id ? 'reply' : 'comment') );
-
+
/* stack for don't close the compose form if the user click on a button */
- this.$('.oe_msg_footer').on('mousedown', _.bind( function () { this.stay_open = true; }, this));
+ this.$('.oe_msg_left, .oe_msg_center').on('mousedown', _.bind( function () { this.stay_open = true; }, this));
+ this.$('.oe_msg_left, .oe_msg_content').on('mouseup', _.bind( function () { this.$('textarea').focus(); }, this));
+
var ev_stay = {};
ev_stay.mouseup = ev_stay.keydown = ev_stay.focus = function () { self.stay_open = false; };
this.$('textarea:not(.oe_compact)').on(ev_stay);
@@ -491,6 +494,8 @@ openerp.mail = function (session) {
// event: delete child attachments off the oe_msg_attachment_list box
this.$(".oe_msg_attachment_list").on('click', '.oe_delete', this.on_attachment_delete);
+
+ this.$(".oe_emails_from").on('change', 'input', this.on_checked_email_from);
},
on_compose_fullmail: function (default_composition_mode) {
@@ -559,46 +564,79 @@ openerp.mail = function (session) {
}
},
- /*post a message and fetch the message*/
- on_message_post: function (event) {
+ check_recipient_partners: function (emails) {
var self = this;
-
- var comment_node = this.$('textarea');
- var body = comment_node.val();
-
- if (this.do_check_attachment_upload() && (this.attachment_ids.length || body.match(/\S+/))) {
- //session.web.blockUI();
- this.parent_thread.ds_thread.call('message_post_user_api', [
- this.context.default_res_id,
- body,
- false,
- this.context.default_parent_id,
- _.map(this.attachment_ids, function (file) {return file.id;}),
- this.parent_thread.context
- ]).done(function (record) {
- var thread = self.parent_thread;
- var root = thread == self.options.root_thread;
- if (self.options.display_indented_thread < self.thread_level && thread.parent_message) {
- var thread = thread.parent_message.parent_thread;
- }
- // create object and attach to the thread object
- thread.message_fetch([['id', 'child_of', [self.id]]], false, [record], function (arg, data) {
- var message = thread.create_message_object( data[0] );
- // insert the message on dom
- thread.insert_message( message, root ? undefined : self.$el, root );
+ var deferreds = [];
+ var ds_partner = new session.web.DataSetSearch(this, 'res.partner');
+ _.each(emails, function (email) {
+ ds_partner.call('search', [[['email', '=', email]]]).then(function (partner_ids) {
+ if (!partner_ids.length) {
+ var deferred = $.Deferred();
+ var pop = new session.web.form.FormOpenPopup(this);
+ pop.show_element(
+ 'res.partner',
+ 0,
+ {
+ 'default_email': email,
+ 'force_email': true,
+ 'ref': "compound_context",
+ },
+ {
+ title: _t("Please complete partner's informations"),
+ }
+ );
+ pop.on('write_completed, closed', self, function () {
+ deferred.resolve();
});
- self.on_cancel();
- //session.web.unblockUI();
- });
- return true;
+ deferreds.push(deferred);
+ }
+ });
+ });
+ return $.when.apply( $, deferreds );
+ },
+
+ on_message_post: function (event) {
+ var self = this;
+ if (this.do_check_attachment_upload() && (this.attachment_ids.length || this.$('textarea').val().match(/\S+/))) {
+ // create list of new partners
+ var extra_email = _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]});
+ this.check_recipient_partners(extra_email).done(function () {
+ self.do_send_message_post();
+ });
}
},
+ /*do post a message and fetch the message*/
+ do_send_message_post: function () {
+ var self = this;
+ this.parent_thread.ds_thread._model.call('message_post_user_api', [this.context.default_res_id], {
+ 'body': this.$('textarea').val(),
+ 'subject': false,
+ 'parent_id': this.context.default_parent_id,
+ 'attachment_ids': _.map(this.attachment_ids, function (file) {return file.id;}),
+ 'extra_emails': _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]}),
+ 'context': this.parent_thread.context,
+ }).done(function (message_id) {
+ var thread = self.parent_thread;
+ var root = thread == self.options.root_thread;
+ if (self.options.display_indented_thread < self.thread_level && thread.parent_message) {
+ var thread = thread.parent_message.parent_thread;
+ }
+ // create object and attach to the thread object
+ thread.message_fetch([["id", "=", message_id]], false, [message_id], function (arg, data) {
+ var message = thread.create_message_object( data[0] );
+ // insert the message on dom
+ thread.insert_message( message, root ? undefined : self.$el, root );
+ });
+ self.on_cancel();
+ });
+ },
+
/* convert the compact mode into the compose message
*/
on_compose_expandable: function (event) {
-
- if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/))) {
+ this.get_emails_from();
+ if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/) && !this.attachment_ids.length)) {
this.show_composer = !this.show_composer || this.stay_open;
this.reinit();
}
@@ -620,6 +658,41 @@ openerp.mail = function (session) {
if (!this.show_composer) {
this.reinit();
}
+ },
+
+ get_emails_from: function () {
+ var self = this;
+ var messages = [];
+
+ if (this.parent_thread.parent_message) {
+ // go to the parented message
+ var message = this.parent_thread.parent_message;
+ var parent_message = message.parent_id ? message.parent_thread.parent_message : message;
+ var messages = [parent_message].concat(parent_message.get_childs());
+ } else if (this.options.emails_from_on_composer) {
+ // get all wall messages if is not a mail.Wall
+ _.each(this.options.root_thread.messages, function (msg) {messages.push(msg); messages.concat(msg.get_childs());});
+ }
+
+ var emails_from = _.map(_.filter(messages,
+ function (thread) {return thread.author_id && !thread.author_id[0];}),
+ function (thread) {return thread.author_id[1];});
+
+ return _.each(emails_from, function (email_from) {
+ if (!_.find(self.emails_from, function (from) {return from[0] == email_from;})) {
+ self.emails_from.push([email_from, true]);
+ }
+ });
+ },
+
+ on_checked_email_from: function (event) {
+ var $input = $(event.target);
+ var email = $input.attr("data");
+ _.each(this.emails_from, function (email_from) {
+ if (email_from[0] == email) {
+ email_from[1] = $input.is(":checked");
+ }
+ });
}
});
@@ -982,9 +1055,11 @@ openerp.mail = function (session) {
this.is_private = datasets.is_private || false;
this.author_id = datasets.author_id || false;
this.thread_level = (datasets.thread_level+1) || 0;
- this.partner_ids = datasets.partner_ids || [];
- if (datasets.author_id)
- this.partner_ids.push(datasets.author_id);
+ datasets.partner_ids = datasets.partner_ids || [];
+ if (datasets.author_id && ! _.contains(datasets.partner_ids, datasets.author_id) && datasets.author_id[0]) {
+ datasets.partner_ids.push(datasets.author_id);
+ }
+ this.partner_ids = datasets.partner_ids;
this.messages = [];
this.options.flat_mode = !!(this.options.display_indented_thread > this.thread_level ? this.options.display_indented_thread - this.thread_level : 0);
@@ -1450,6 +1525,7 @@ openerp.mail = function (session) {
'message_ids': undefined,
'compose_as_todo' : false,
'readonly' : false,
+ 'emails_from_on_composer': true,
}, this.action.params);
this.action.params.help = this.action.help || false;
@@ -1490,7 +1566,7 @@ openerp.mail = function (session) {
$(window).resize( _.bind(this.thread.on_scroll, this.thread) );
this.$el.resize( _.bind(this.thread.on_scroll, this.thread) );
window.setTimeout( _.bind(this.thread.on_scroll, this.thread), 500 );
- }
+ },
});
@@ -1527,6 +1603,10 @@ openerp.mail = function (session) {
}
this.domain = this.node.params && this.node.params.domain || [];
+
+ if (!this.__parentedParent.is_action_enabled('edit')) {
+ this.node.params.show_link = false;
+ }
},
start: function () {
@@ -1615,6 +1695,7 @@ openerp.mail = function (session) {
'show_record_name': true,
'show_compact_message': this.action.params.view_mailbox ? false : 1,
'view_inbox': false,
+ 'emails_from_on_composer': false,
}, this.action.params);
},
diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js
index 0645c2b9225..1e481271eda 100644
--- a/addons/mail/static/src/js/mail_followers.js
+++ b/addons/mail/static/src/js/mail_followers.js
@@ -26,12 +26,16 @@ openerp_mail_followers = function(session, mail) {
this._super.apply(this, arguments);
this.image = this.node.attrs.image || 'image_small';
this.comment = this.node.attrs.help || false;
- this.displayed_nb = this.node.attrs.displayed_nb || 10;
+ this.displayed_limit = this.node.attrs.displayed_nb || 10;
+ this.displayed_nb = this.displayed_limit;
this.ds_model = new session.web.DataSetSearch(this, this.view.model);
this.ds_follow = new session.web.DataSetSearch(this, this.field.relation);
this.ds_users = new session.web.DataSetSearch(this, 'res.users');
this.value = [];
+ this.followers = [];
+
+ this.view_is_editable = this.__parentedParent.is_action_enabled('edit');
},
start: function() {
@@ -69,29 +73,47 @@ openerp_mail_followers = function(session, mail) {
// event: click on a subtype, that (un)subscribe for this subtype
this.$el.on('click', '.oe_subtype_list input', self.do_update_subscription);
// event: click on 'invite' button, that opens the invite wizard
- this.$('.oe_invite').on('click', function (event) {
- action = {
- type: 'ir.actions.act_window',
- res_model: 'mail.wizard.invite',
- view_mode: 'form',
- view_type: 'form',
- views: [[false, 'form']],
- target: 'new',
- context: {
- 'default_res_model': self.view.dataset.model,
- 'default_res_id': self.view.datarecord.id,
- },
- }
- self.do_action(action, {
- on_close: function() {
- self.read_value();
- },
- });
+ this.$('.oe_invite').on('click', self.on_invite_follower);
+ this.$el.on('click', '.oe_remove_follower', self.on_remove_follower);
+ this.$el.on('click', '.oe_show_more', self.on_show_more_followers)
+ },
+
+ on_invite_follower: function (event) {
+ var self = this;
+ var action = {
+ type: 'ir.actions.act_window',
+ res_model: 'mail.wizard.invite',
+ view_mode: 'form',
+ view_type: 'form',
+ views: [[false, 'form']],
+ target: 'new',
+ context: {
+ 'default_res_model': this.view.dataset.model,
+ 'default_res_id': this.view.datarecord.id,
+ },
+ }
+ this.do_action(action, {
+ on_close: function() {
+ self.read_value();
+ },
});
},
+ on_show_more_followers: function (event) {
+ this.displayed_nb += this.displayed_limit;
+ this.display_followers(false);
+ },
+
+ on_remove_follower: function (event) {
+ var partner_id = $(event.target).data('id');
+ var context = new session.web.CompoundContext(this.build_context(), {});
+ return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id], [partner_id], context])
+ .then(this.proxy('read_value'));
+ },
+
read_value: function () {
var self = this;
+ this.displayed_nb = this.displayed_limit;
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
self.value = results[0].message_follower_ids;
self.render_value();
@@ -145,20 +167,20 @@ openerp_mail_followers = function(session, mail) {
/** Display the followers */
display_followers: function (records) {
var self = this;
- records = records || [];
- this.message_is_follower = this.set_is_follower(records);
+ this.followers = records || this.followers;
+ this.message_is_follower = this.set_is_follower(this.followers);
// clean and display title
var node_user_list = this.$('.oe_follower_list').empty();
- this.$('.oe_follower_title').html(this._format_followers(records.length));
+ this.$('.oe_follower_title').html(this._format_followers(this.followers.length));
// truncate number of displayed followers
- truncated = records.splice(0, this.displayed_nb);
+ var truncated = this.followers.slice(0, this.displayed_nb);
_(truncated).each(function (record) {
record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id);
- $(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(node_user_list);
+ $(session.web.qweb.render('mail.followers.partner', {'record': record, 'widget': self})).appendTo(node_user_list);
});
// FVA note: be sure it is correctly translated
- if (truncated.length < records.length) {
- $('<div class="oe_partner">And ' + (records.length - truncated.length) + ' more.</div>').appendTo(node_user_list);
+ if (truncated.length < this.followers.length) {
+ $(session.web.qweb.render('mail.followers.show_more', {'number': (this.followers.length - truncated.length)} )).appendTo(node_user_list);
}
},
@@ -196,18 +218,23 @@ openerp_mail_followers = function(session, mail) {
var subtype_list_ul = this.$('.oe_subtype_list');
subtype_list_ul.empty();
var records = data[this.view.datarecord.id || this.view.dataset.ids[0]].message_subtype_data;
- _(records).each(function (record, record_name) {
- record.name = record_name;
- record.followed = record.followed || undefined;
- $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') );
- });
+ if (records.length > 1) {
+ _(records).each(function (record, record_name) {
+ record.name = record_name;
+ record.followed = record.followed || undefined;
+ $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') );
+ });
+ }
},
do_follow: function () {
- _(this.$('.oe_msg_subtype_check')).each(function (record) {
+ var context = new session.web.CompoundContext(this.build_context(), {});
+ this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context])
+ .then(this.proxy('read_value'));
+
+ _.each(this.$('.oe_subtype_list input'), function (record) {
$(record).attr('checked', 'checked');
});
- this.do_update_subscription();
},
do_unfollow: function () {
@@ -229,9 +256,13 @@ openerp_mail_followers = function(session, mail) {
}
});
- var context = new session.web.CompoundContext(this.build_context(), {});
- return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist : undefined, context])
- .then(this.proxy('read_value'));
+ if (!checklist.length) {
+ this.do_unfollow();
+ } else {
+ var context = new session.web.CompoundContext(this.build_context(), {});
+ return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], checklist, context])
+ .then(this.proxy('read_value'));
+ }
},
});
};
diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml
index 3c510813029..4b3c31525d4 100644
--- a/addons/mail/static/src/xml/mail.xml
+++ b/addons/mail/static/src/xml/mail.xml
@@ -79,7 +79,7 @@
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img>
<div class='oe_name'><t t-raw='attachment.name' /></div>
</a>
- <div class='oe_delete oe_e' title="Delete this attachment" t-attf-data-id="{attachment.id}">[</div>
+ <div class='oe_delete oe_e' title="Delete this attachment" t-att-data-id="attachment.id">[</div>
<div class='oe_progress_bar'>
uploading
</div>
@@ -91,7 +91,7 @@
<img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img>
<div class='oe_name'><t t-raw='attachment.name' /></div>
</a>
- <div class='oe_delete oe_e'>[</div>
+ <div class='oe_delete oe_e' title="Delete this attachment" t-att-data-id="attachment.id">[</div>
<div class='oe_progress_bar'>
uploading
</div>
@@ -113,19 +113,28 @@
<t t-if="!widget.parent_thread.parent_message.record_name">this document</t>
</span>
</t>
- <t t-if="!widget.is_private and widget.partner_ids.length"> and </t>
+ <t t-if="!widget.is_private and (widget.partner_ids.length or (widget.author_id and widget.author_id[0]))"> and </t>
<t t-set="inc" t-value="0"/>
- <t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner">
+ <t t-foreach="widget.partner_ids" t-as="partner">
<span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/>
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-raw="partner[1]"/></a>
<t t-if="!widget.options.show_link" t-raw="partner[1]"/>
- </span><t t-set="inc" t-value="inc+1"/>
+ </span>
+ <t t-set="inc" t-value="inc+1"/>
</t>
- <t t-if="widget.partner_ids.length>=3">
- <span class="oe_more">, <a><t t-raw="widget.partner_ids.length-3"/> others...</a></span>
+ <t t-if="widget.partner_ids.length > 3">
+ <span class="oe_more">, <a><t t-raw="widget.partner_ids.length - 3"/> others...</a></span>
<a class="oe_more_hidden">&lt;&lt;&lt;</a>
</t>
</div>
+ <div class="oe_emails_from">
+ <t t-foreach='widget.emails_from' t-as='email_from'>
+ <label title="Add them into recipients and followers">
+ <input type="checkbox" t-att-checked="email_from[1] ? 'checked' : undefind" t-att-data="email_from[0]"/>
+ <t t-raw="email_from[0]"/>
+ </label>
+ </t>
+ </div>
</t>
<!--
@@ -232,8 +241,8 @@
<t t-if="widget.attachment_ids.length > 0">
<div class="oe_msg_attachment_list"></div>
</t>
- <a t-if="widget.author_id and widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
- <span t-if="widget.author_id and !widget.options.show_link"><t t-raw="widget.author_id[1]"/></span>
+ <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
+ <span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-raw="widget.author_id[1]"/></span>
<span class='oe_subtle'>•</span>
<span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span>
<span t-if="!widget.options.readonly" class='oe_subtle'>•</span>
diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml
index f0a603e7f98..459f13155a0 100644
--- a/addons/mail/static/src/xml/mail_followers.xml
+++ b/addons/mail/static/src/xml/mail_followers.xml
@@ -20,7 +20,7 @@
<hr size="2"></hr>
<div class='oe_follower_title_box'>
<h4 class='oe_follower_title'>Followers</h4>
- <a href='#' class="oe_invite">Invite others</a>
+ <a t-if="widget.view_is_editable" href='#' class="oe_invite">Add others</a>
</div>
<div class="oe_follower_list"></div>
</div>
@@ -32,6 +32,7 @@
<div t-name="mail.followers.partner" class='oe_partner'>
<img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/>
<a t-attf-href="#model=res.partner&amp;id=#{record.id}"><t t-raw="record.name"/></a>
+ <span t-if="widget.view_is_editable" class="oe_remove_follower oe_e" title="Remove this follower" t-att-data-id="record.id">X</span>
</div>
<!--
@@ -47,4 +48,8 @@
</table>
</t>
+ <t t-name="mail.followers.show_more">
+ <div class="oe_partner oe_show_more">And <t t-raw="number"/> more.</div>
+ </t>
+
</template>