summaryrefslogtreecommitdiff
path: root/addons/mail/static/src
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2016-02-17 18:01:11 +0100
committerChristophe Simonis <chs@odoo.com>2016-02-17 18:01:11 +0100
commit87a01c75ef1dde98bc31f714d8ac4b2ea598e316 (patch)
tree4fe33a648fc7de34294113ff2c69e2e28b133b85 /addons/mail/static/src
parentd70fde0330550d510668e49807da83e646e8ccec (diff)
parent5be43b8d9ae4485ac28e9afb7dd7cdecefb58abc (diff)
[MERGE] forward port of branch saas-7 up to 5be43b8
Diffstat (limited to 'addons/mail/static/src')
-rw-r--r--addons/mail/static/src/js/chat_manager.js16
-rw-r--r--addons/mail/static/src/js/chatter.js23
-rw-r--r--addons/mail/static/src/js/client_action.js2
-rw-r--r--addons/mail/static/src/js/composer.js58
-rw-r--r--addons/mail/static/src/less/chat_window.less2
-rw-r--r--addons/mail/static/src/less/thread.less4
-rw-r--r--addons/mail/static/src/xml/thread.xml12
7 files changed, 51 insertions, 66 deletions
diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js
index d0aceeaaac5..b35b6d05830 100644
--- a/addons/mail/static/src/js/chat_manager.js
+++ b/addons/mail/static/src/js/chat_manager.js
@@ -134,7 +134,7 @@ function strip_html (node, transform_children) {
function inline (node, transform_children) {
if (node.nodeType === 3) return node.data;
if (node.tagName === "BR") return " ";
- if (node.tagName.match(/^(A|P|DIV|PRE)$/)) return transform_children();
+ if (node.tagName.match(/^(A|P|DIV|PRE|BLOCKQUOTE)$/)) return transform_children();
node.innerHTML = transform_children();
return node.outerHTML;
}
@@ -148,7 +148,7 @@ function add_message (data, options) {
var msg = _.findWhere(messages, { id: data.id });
if (!msg) {
- msg = make_message(data);
+ msg = chat_manager.make_message(data);
// Keep the array ordered by id when inserting the new message
messages.splice(_.sortedIndex(messages, msg, 'id'), 0, msg);
_.each(msg.channel_ids, function (channel_id) {
@@ -298,7 +298,7 @@ function add_channel (data, options) {
chat_manager.bus.trigger("channel_toggle_fold", channel);
}
} else {
- channel = make_channel(data, options);
+ channel = chat_manager.make_channel(data, options);
channels.push(channel);
channels = _.sortBy(channels, function (channel) { return channel.name.toLowerCase(); });
if (!options.silent) {
@@ -677,6 +677,10 @@ function on_presence_notification (data) {
// Public interface
//----------------------------------------------------------------------------------
var chat_manager = {
+ // these two functions are exposed for extensibility purposes and shouldn't be called by other modules
+ make_message: make_message,
+ make_channel: make_channel,
+
post_message: function (data, options) {
options = options || {};
var msg = {
@@ -773,9 +777,9 @@ var chat_manager = {
return $.when();
}
},
- mark_all_as_read: function (channel) {
- if ((!channel && needaction_counter) || (channel && channel.needaction_counter)) {
- return MessageModel.call('mark_all_as_read', channel ? [[channel.id]] : []);
+ mark_all_as_read: function (channel, domain) {
+ if ((channel.id === "channel_inbox" && needaction_counter) || (channel && channel.needaction_counter)) {
+ return MessageModel.call('mark_all_as_read', [], {channel_ids: channel.id !== "channel_inbox" ? [channel.id] : [], domain: domain});
}
return $.when();
},
diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js
index fb39b595415..3b37cc66d43 100644
--- a/addons/mail/static/src/js/chatter.js
+++ b/addons/mail/static/src/js/chatter.js
@@ -33,7 +33,6 @@ var Followers = form_common.AbstractField.extend({
this.image = this.node.attrs.image || 'image_small';
this.comment = this.node.attrs.help || false;
this.ds_model = new data.DataSetSearch(this, this.view.model);
- this.ds_users = new data.DataSetSearch(this, 'res.users');
this.value = [];
this.followers = [];
@@ -191,25 +190,11 @@ var Followers = form_common.AbstractField.extend({
fetch_followers: function (value_) {
this.value = value_ || [];
return ajax.jsonRpc('/mail/read_followers', 'call', {'follower_ids': this.value})
- .then(this.proxy('display_followers'), this.proxy('fetch_generic'))
+ .then(this.proxy('display_followers'), this.proxy('display_generic'))
.then(this.proxy('display_buttons'))
.then(this.proxy('fetch_subtypes'));
},
- /** Read on res.partner failed: fall back on a generic case
- - fetch current user partner_id (call because no other smart solution currently) FIXME
- - then display a generic message about followers */
- fetch_generic: function () {
- var self = this;
-
- return this.ds_users.call('read', [[session.uid], ['partner_id']])
- .then(function (results) {
- var pid = results[0].partner_id[0];
- self.message_is_follower = (_.indexOf(self.value, pid) !== -1);
- })
- .then(self.proxy('display_generic'));
- },
-
_format_followers: function (count){
var str = '';
if(count <= 0){
@@ -222,9 +207,11 @@ var Followers = form_common.AbstractField.extend({
return str;
},
- /* Display generic info about follower, for people not having access to res_partner */
+ /** Read on res.partner failed: only display the number of followers */
display_generic: function () {
- this.$('.o_followers_list').empty();
+ this.$('.o_followers_actions').hide();
+ this.$('.o_followers_list').hide();
+ this.$('.o_followers_title_box > button').prop('disabled', true);
this.$('.o_followers_count').html(this._format_followers(this.value.length));
},
diff --git a/addons/mail/static/src/js/client_action.js b/addons/mail/static/src/js/client_action.js
index ff4b96a0c24..6d3ce922e8f 100644
--- a/addons/mail/static/src/js/client_action.js
+++ b/addons/mail/static/src/js/client_action.js
@@ -211,7 +211,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
self.$('.o_mail_chat_sidebar').slideToggle(200);
});
this.$buttons.on('click', '.o_mail_chat_button_mark_read', function () {
- chat_manager.mark_all_as_read();
+ chat_manager.mark_all_as_read(self.channel, self.domain);
});
this.$buttons.on('click', '.o_mail_chat_button_unstar_all', chat_manager.unstar_all);
this.$buttons.on('click', '.o_mail_chat_button_new_message', this.on_click_new_message);
diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js
index 6ffd2bc63c3..4fafe8427eb 100644
--- a/addons/mail/static/src/js/composer.js
+++ b/addons/mail/static/src/js/composer.js
@@ -27,6 +27,8 @@ var accented_letters_mapping = {
' ': '[()\\[\\]]',
};
+var NON_BREAKING_SPACE = '\u00a0';
+
var MENTION_PARTNER_DELIMITER = '@';
var MENTION_CHANNEL_DELIMITER = '#';
@@ -71,6 +73,8 @@ var MentionManager = Widget.extend({
var selected_suggestion = _.find(_.flatten(this.get('mention_suggestions')), function (s) {
return s.id === id;
});
+ // replace white spaces with non-breaking spaces to facilitate mentions detection in text
+ selected_suggestion.name = selected_suggestion.name.replace(/ /g, NON_BREAKING_SPACE);
var get_mention_index = function (matches, cursor_position) {
for (var i=0; i<matches.length; i++) {
if (cursor_position <= matches[i].index) {
@@ -121,9 +125,16 @@ var MentionManager = Widget.extend({
return this.open;
},
+ /**
+ * Returns the mentions of the given listener that haven't been erased from the composer's input
+ */
get_listener_selection: function (delimiter) {
var listener = _.findWhere(this.listeners, {delimiter: delimiter});
- return listener ? listener.selection : [];
+ if (listener) {
+ var input_mentions = this.composer.$input.val().match(new RegExp(delimiter+'[^ ]+', 'g'));
+ return this._validate_selection(listener.selection, input_mentions);
+ }
+ return [];
},
get_listener_selections: function () {
@@ -200,33 +211,6 @@ var MentionManager = Widget.extend({
},
/**
- * Checks if a listener's selection should be updated after DELETE or BACKSPACE keypress
- */
- check_remove: function () {
- var self = this;
- var to_remove = [];
- var selection = this._get_selection_positions();
- var deleted_binf = selection.start;
- var deleted_bsup = selection.end;
-
- _.each(this.listeners, function (listener) {
- var mention_selection = listener.selection;
- var matches = self._get_match(self.composer.$input.val(), listener);
- for (var i=0; i<matches.length; i++) {
- var m = matches[i];
- var m1 = m.index;
- var m2 = m.index + m[0].length;
- if (deleted_binf <= m2 && m1 < deleted_bsup) {
- to_remove.push(mention_selection[i]);
- }
- }
- if (to_remove.length) {
- listener.selection = _.difference(mention_selection, to_remove);
- }
- });
- },
-
- /**
* Replaces mentions appearing in the string 's' by html links with proper redirection
*/
generate_links: function (s) {
@@ -242,7 +226,8 @@ var MentionManager = Widget.extend({
for (var i=0; i<matches.length; i++) {
var match = matches[i];
var end_index = match.index + match[0].length;
- var match_name = match[0].substring(1);
+ // put back white spaces instead of non-breaking spaces in mention's name
+ var match_name = match[0].substring(1).replace(new RegExp(NON_BREAKING_SPACE, 'g'), ' ');
var href = base_href + _.str.sprintf("#model=%s&id=%s", listener.model, selection[i].id);
var processed_text = _.str.sprintf(mention_link, href, listener.redirect_classname, selection[i].id, listener.model, listener.delimiter, match_name);
var subtext = s.substring(start_index, end_index).replace(match[0], processed_text);
@@ -303,6 +288,16 @@ var MentionManager = Widget.extend({
this.open = false;
}
},
+ _validate_selection: function (selection, input_mentions) {
+ var validated_selection = [];
+ _.each(input_mentions, function (mention) {
+ var validated_mention = _.findWhere(selection, {name: mention.slice(1)});
+ if (validated_mention) {
+ validated_selection.push(validated_mention);
+ }
+ });
+ return validated_selection;
+ },
// Cursor position and selection utils
_get_selection_positions: function () {
@@ -477,11 +472,6 @@ var BasicComposer = Widget.extend({
event.preventDefault();
}
break;
- // BACKSPACE, DELETE: check if need to remove a mention
- case $.ui.keyCode.BACKSPACE:
- case $.ui.keyCode.DELETE:
- this.mention_manager.check_remove();
- break;
// ENTER: submit the message only if the dropdown mention proposition is not displayed
case $.ui.keyCode.ENTER:
if (this.mention_manager.is_open()) {
diff --git a/addons/mail/static/src/less/chat_window.less b/addons/mail/static/src/less/chat_window.less
index d525c1d9ddc..3d61cb0cc19 100644
--- a/addons/mail/static/src/less/chat_window.less
+++ b/addons/mail/static/src/less/chat_window.less
@@ -13,7 +13,7 @@
background-color: @o-chat-window-bg;
border: 1px solid gray;
border-radius: 3px;
- z-index: 2;
+ z-index: 3;
@media (max-width: @screen-xs-max) {
width: 100%;
diff --git a/addons/mail/static/src/less/thread.less b/addons/mail/static/src/less/thread.less
index 7da1a13802e..f737999bfe6 100644
--- a/addons/mail/static/src/less/thread.less
+++ b/addons/mail/static/src/less/thread.less
@@ -161,4 +161,8 @@
margin-bottom: 20px;
font-size: 20px;
}
+
+ .o_mail_no_content {
+ .o-webclient-padding();
+ }
}
diff --git a/addons/mail/static/src/xml/thread.xml b/addons/mail/static/src/xml/thread.xml
index 6ed0700be11..5c0c958bb69 100644
--- a/addons/mail/static/src/xml/thread.xml
+++ b/addons/mail/static/src/xml/thread.xml
@@ -12,14 +12,14 @@
<t t-if="options.display_empty_channel">
<t t-call="mail.EmptyChannel" />
</t>
- <t t-if="options.display_no_match">
+ <div t-if="options.display_no_match" class="o_mail_no_content">
<div class="o_thread_title">No matches found</div>
<div>No message matches your search. Try to change your search filters.</div>
- </t>
+ </div>
</t>
<!-- When a channel is empty-->
- <div t-name="mail.EmptyChannel">
+ <div t-name="mail.EmptyChannel" class="o_mail_no_content">
<t t-if="options.channel_id==='channel_inbox'">
<div class="o_thread_title">Congratulations, your inbox is empty</div>
<div>New messages appear here.</div>
@@ -100,12 +100,12 @@
<i t-if="options.display_stars &amp;&amp; !message.is_system_notification"
t-att-class="'fa fa-lg o_thread_message_star ' + (message.is_starred ? 'fa-star' : 'fa-star-o')"
t-att-data-message-id="message.id" title="Mark as Todo"/>
- <i t-if="message.is_needaction &amp;&amp; options.display_needactions"
- class="fa fa-check o_thread_message_needaction"
- t-att-data-message-id="message.id" title="Mark as Read"/>
<i t-if="message.record_name &amp;&amp; message.model != 'mail.channel' &amp;&amp; options.display_reply_icon"
class="fa fa-reply o_thread_message_reply"
t-att-data-message-id="message.id" title="Reply"/>
+ <i t-if="message.is_needaction &amp;&amp; options.display_needactions"
+ class="fa fa-check o_thread_message_needaction"
+ t-att-data-message-id="message.id" title="Mark as Read"/>
</span>
</p>
<t t-if="message.tracking_value_ids &amp;&amp; message.tracking_value_ids.length &gt; 0">