diff options
| author | Christophe Simonis <chs@odoo.com> | 2016-02-02 14:55:52 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2016-02-02 14:55:52 +0100 |
| commit | 04416a5a6f1a3b4cf1a8bed8e9aee9c30c91a03e (patch) | |
| tree | 1fd974be09d12c53ed02a221de553f6f83efc253 /addons/mail/static/src/js | |
| parent | 7e3d6e92b6a7af27d8c2ebb0dbbecba28c9f1877 (diff) | |
| parent | 469e04e97c2aa60d9d41bd430e0aeba77ee6f9dd (diff) | |
[MERGE] forward port of branch saas-9 up to 469e04e
Diffstat (limited to 'addons/mail/static/src/js')
| -rw-r--r-- | addons/mail/static/src/js/chat_manager.js | 23 | ||||
| -rw-r--r-- | addons/mail/static/src/js/chat_window.js | 7 | ||||
| -rw-r--r-- | addons/mail/static/src/js/chatter.js | 23 | ||||
| -rw-r--r-- | addons/mail/static/src/js/client_action.js | 4 | ||||
| -rw-r--r-- | addons/mail/static/src/js/composer.js | 29 | ||||
| -rw-r--r-- | addons/mail/static/src/js/systray.js | 61 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread.js | 23 | ||||
| -rw-r--r-- | addons/mail/static/src/js/window_manager.js | 3 |
8 files changed, 126 insertions, 47 deletions
diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js index 6fd85e33719..2db02429d7a 100644 --- a/addons/mail/static/src/js/chat_manager.js +++ b/addons/mail/static/src/js/chat_manager.js @@ -25,6 +25,7 @@ var channels = []; var channels_preview_def; var channel_defs = {}; var chat_unread_counter = 0; +var unread_conversation_counter = 0; var emojis = []; var emoji_substitutions = {}; var needaction_counter = 0; @@ -146,7 +147,7 @@ function add_message (data, options) { channel.hidden = false; chat_manager.bus.trigger('new_channel', channel); } - if (!msg.author_id || msg.author_id[0] !== session.partner_id) { + if (channel.type !== 'static' && !msg.is_author && !msg.is_system_notification) { if (options.increment_unread) { update_channel_unread_counter(channel, channel.unread_counter+1); } @@ -176,7 +177,9 @@ function make_message (data) { date: moment(time.str_to_datetime(data.date)), message_type: data.message_type, subtype_description: data.subtype_description, + is_author: data.author_id && data.author_id[0] === session.partner_id, is_note: data.is_note, + is_system_notification: data.message_type === 'notification' && data.model === 'mail.channel', attachment_ids: data.attachment_ids, subject: data.subject, email_from: data.email_from, @@ -240,11 +243,7 @@ function make_message (data) { } // Don't redirect on author clicked of self-posted messages - if (msg.author_id && msg.author_id[0] === session.partner_id) { - msg.author_redirect = false; - } else { - msg.author_redirect = true; - } + msg.author_redirect = !msg.is_author; // Compute the avatar_url if (msg.author_id && msg.author_id[0]) { @@ -449,8 +448,13 @@ function fetch_document_messages (ids, options) { } function update_channel_unread_counter (channel, counter) { + if (channel.unread_counter > 0 && counter === 0) { + unread_conversation_counter = Math.max(0, unread_conversation_counter-1); + } else if (channel.unread_counter === 0 && counter > 0) { + unread_conversation_counter++; + } if (channel.is_chat) { - chat_unread_counter = chat_unread_counter - channel.unread_counter + counter; + chat_unread_counter = Math.max(0, chat_unread_counter - channel.unread_counter + counter); } channel.unread_counter = counter; chat_manager.bus.trigger("update_channel_unread_counter", channel); @@ -807,6 +811,9 @@ var chat_manager = { get_chat_unread_counter: function () { return chat_unread_counter; }, + get_unread_conversation_counter: function () { + return unread_conversation_counter; + }, get_last_seen_message: function (channel) { if (channel.last_seen_message_id) { @@ -814,7 +821,7 @@ var chat_manager = { var msg = _.findWhere(messages, {id: channel.last_seen_message_id}); if (msg) { var i = _.sortedIndex(messages, msg, 'id') + 1; - while (i < messages.length && messages[i].author_id && messages[i].author_id[0] === session.partner_id) { + while (i < messages.length && (messages[i].is_author || messages[i].is_system_notification)) { msg = messages[i]; i++; } diff --git a/addons/mail/static/src/js/chat_window.js b/addons/mail/static/src/js/chat_window.js index 95ac9dd8897..0e0289c394e 100644 --- a/addons/mail/static/src/js/chat_window.js +++ b/addons/mail/static/src/js/chat_window.js @@ -15,7 +15,9 @@ var HEIGHT_FOLDED = '28px'; return Widget.extend({ template: "mail.ChatWindow", events: { + "click .o_chat_input": "focus_input", // focus even if jquery's blockUI is enabled "keydown .o_chat_input": "on_keydown", + "keypress .o_chat_input": "on_keypress", "click .o_chat_window_close": "on_click_close", "click .o_chat_title": "on_click_fold", }, @@ -28,6 +30,7 @@ return Widget.extend({ this.options = _.defaults(options || {}, { display_stars: true, placeholder: _t("Say something"), + input_less: false, }); this.unread_msgs = unread_msgs || 0; this.is_hidden = false; @@ -90,7 +93,11 @@ return Widget.extend({ this.is_hidden = _.isBoolean(display) ? !display : !this.is_hidden; this._super.apply(this, arguments); }, + on_keypress: function (event) { + event.stopPropagation(); // to prevent jquery's blockUI to cancel event + }, on_keydown: function (event) { + event.stopPropagation(); // to prevent jquery's blockUI to cancel event // ENTER key (avoid requiring jquery ui for external livechat) if (event.which === 13) { var content = _.str.trim(this.$input.val()); diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index dc528b2b1aa..fb39b595415 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -451,7 +451,6 @@ var ChatterComposer = composer.BasicComposer.extend({ record_name: false, is_log: false, internal_subtypes: [], - default_body: '', }); if (this.options.is_log) { this.options.send_text = _('Log'); @@ -468,13 +467,6 @@ var ChatterComposer = composer.BasicComposer.extend({ return $.when(this._super.apply(this, arguments), this.message_get_suggested_recipients()); }, - start: function () { - var self = this; - return this._super().then(function () { - self.$input.val(self.options.default_body); - }); - }, - should_send: function () { return false; }, @@ -726,6 +718,16 @@ var Chatter = form_common.AbstractField.extend({ start: function () { var self = this; + // Hide the chatter in 'create' mode + this.view.on("change:actual_mode", this, this.check_visibility); + this.check_visibility(); + var $container = this.$el.parent(); + if ($container.hasClass('oe_chatter')) { + this.$el + .addClass($container.attr("class")) + .unwrap(); + } + // Move the follower's widget (if any) inside the chatter this.followers = this.field_manager.fields.message_follower_ids; if (this.followers) { @@ -759,6 +761,10 @@ var Chatter = form_common.AbstractField.extend({ }); }, + check_visibility: function () { + this.set({"force_invisible": this.view.get("actual_mode") === "create"}); + }, + fetch_and_render_thread: function (ids, options) { var self = this; options = options || {}; @@ -906,6 +912,7 @@ var Chatter = form_common.AbstractField.extend({ is_log: options && options.is_log, record_name: this.record_name, default_body: old_composer && old_composer.$input.val(), + default_mention_selections: old_composer && old_composer.mention_get_listener_selections(), }); this.composer.on('input_focused', this, function () { this.composer.mention_set_prefetched_partners(this.mention_suggestions || []); diff --git a/addons/mail/static/src/js/client_action.js b/addons/mail/static/src/js/client_action.js index d6a5b5ac128..174092887ee 100644 --- a/addons/mail/static/src/js/client_action.js +++ b/addons/mail/static/src/js/client_action.js @@ -371,7 +371,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, { // Hide 'detach' button in static channels self.$buttons .find('.o_mail_chat_button_detach') - .toggle(channel.type !== "static" && !channel.mass_mailing); + .toggle(channel.type !== "static"); // Hide 'invite', 'unsubscribe' and 'settings' buttons in static channels and DM self.$buttons .find('.o_mail_chat_button_invite, .o_mail_chat_button_unsubscribe, .o_mail_chat_button_settings') @@ -446,7 +446,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, { display_load_more: !chat_manager.all_history_loaded(this.channel, this.domain), display_needactions: this.channel.display_needactions, messages_separator_position: this.messages_separator_position, - squash_close_messages: this.channel.type !== 'static', + squash_close_messages: this.channel.type !== 'static' && !this.channel.mass_mailing, display_empty_channel: !messages.length && !this.domain.length, display_no_match: !messages.length && this.domain.length, display_subject: this.channel.mass_mailing || this.channel.id === "channel_inbox", diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js index 5d6de2bad50..92bac153267 100644 --- a/addons/mail/static/src/js/composer.js +++ b/addons/mail/static/src/js/composer.js @@ -27,6 +27,9 @@ var accented_letters_mapping = { ' ': '[()\\[\\]]', }; +var MENTION_PARTNER_DELIMITER = '@'; +var MENTION_CHANNEL_DELIMITER = '#'; + // The MentionManager allows the Composer to register listeners. For each // listener, it detects if the user is currently typing a mention (starting by a // given delimiter). If so, if fetches mention suggestions and renders them. On @@ -106,7 +109,7 @@ var MentionManager = Widget.extend({ * @param {string} [redirect_classname] the classname of the <a> wrapping the mention */ register: function (listener) { - this.listeners.push(_.extend(listener, { + this.listeners.push(_.defaults(listener, { selection: [], })); }, @@ -123,6 +126,14 @@ var MentionManager = Widget.extend({ return listener ? listener.selection : []; }, + get_listener_selections: function () { + var selections = {}; + _.each(this.listeners, function (listener) { + selections[listener.delimiter] = listener.selection; + }); + return selections; + }, + proposition_navigation: function (keycode) { var $active = this.$('.o_mention_proposition.active'); if (keycode === $.ui.keyCode.ENTER) { // selecting proposition @@ -333,6 +344,8 @@ var BasicComposer = Widget.extend({ mention_fetch_limit: 8, mention_partners_restricted: false, // set to true to only suggest prefetched partners send_text: _('Send'), + default_body: '', + default_mention_selections: {}, }); this.context = this.options.context; @@ -344,16 +357,18 @@ var BasicComposer = Widget.extend({ // Mention this.mention_manager = new MentionManager(this); this.mention_manager.register({ - delimiter: '@', + delimiter: MENTION_PARTNER_DELIMITER, fetch_callback: this.mention_fetch_partners.bind(this), model: 'res.partner', redirect_classname: 'o_mail_redirect', + selection: this.options.default_mention_selections[MENTION_PARTNER_DELIMITER], }); this.mention_manager.register({ - delimiter: '#', + delimiter: MENTION_CHANNEL_DELIMITER, fetch_callback: this.mention_fetch_channels.bind(this), model: 'mail.channel', redirect_classname: 'o_channel_redirect', + selection: this.options.default_mention_selections[MENTION_CHANNEL_DELIMITER], }); // Emojis @@ -372,6 +387,7 @@ var BasicComposer = Widget.extend({ this.$input.focus(function () { self.trigger('input_focused'); }); + this.$input.val(this.options.default_body); dom_utils.autoresize(this.$input, {parent: this, min_height: this.options.input_min_height}); // Attachments @@ -635,6 +651,9 @@ var BasicComposer = Widget.extend({ mention_set_prefetched_partners: function (prefetched_partners) { this.mention_prefetched_partners = prefetched_partners; }, + mention_get_listener_selections: function () { + return this.mention_manager.get_listener_selections(); + }, // Others is_empty: function () { @@ -679,6 +698,10 @@ var ExtendedComposer = BasicComposer.extend({ should_send: function () { return false; }, + + focus: function () { + this.$subject_input.focus(); + }, }); return { diff --git a/addons/mail/static/src/js/systray.js b/addons/mail/static/src/js/systray.js index 21d22a12eac..3929947acbb 100644 --- a/addons/mail/static/src/js/systray.js +++ b/addons/mail/static/src/js/systray.js @@ -10,6 +10,42 @@ var chat_manager = require('mail.chat_manager'); var QWeb = core.qweb; /** + * Menu item appended in the systray part of the navbar, redirects to the Inbox in Discuss + * Also displays the needaction counter (= Inbox counter) + */ +var InboxItem = Widget.extend({ + template:'mail.chat.InboxItem', + events: { + "click": "on_click", + }, + start: function () { + this.$needaction_counter = this.$('.o_notification_counter'); + chat_manager.bus.on("update_needaction", this, this.update_counter); + this.update_counter(); + return this._super(); + }, + update_counter: function () { + var counter = chat_manager.get_needaction_counter(); + this.$needaction_counter.text(counter); + this.$el.toggleClass('o_no_notification', !counter); + }, + on_click: function (event) { + event.preventDefault(); + this.discuss_redirect(); + }, + discuss_redirect: _.debounce(function () { + var self = this; + var discuss_ids = chat_manager.get_discuss_ids(); + this.do_action(discuss_ids.action_id, {clear_breadcrumbs: true}).then(function () { + self.trigger_up('hide_app_switcher'); + core.bus.trigger('change_menu_section', discuss_ids.menu_id); + }); + }, 1000, true), +}); + +SystrayMenu.Items.push(InboxItem); + +/** * Menu item appended in the systray part of the navbar * * The menu item indicates the counter of needactions + unread messages in chat channels. When @@ -24,13 +60,11 @@ var MessagingMenu = Widget.extend({ "click .o_filter_button": "on_click_filter_button", "click .o_new_message": "on_click_new_message", "click .o_mail_channel_preview": "on_click_channel", - "click .o_redirect_to_discuss": "on_click_redirect_to_discuss", }, start: function () { this.$filter_buttons = this.$('.o_filter_button'); this.$channels_preview = this.$('.o_mail_navbar_dropdown_channels'); this.filter = false; - chat_manager.bus.on("update_needaction", this, this.update_counter); chat_manager.bus.on("update_channel_unread_counter", this, this.update_counter); this.update_counter(); return this._super(); @@ -39,9 +73,10 @@ var MessagingMenu = Widget.extend({ return this.$el.hasClass('open'); }, update_counter: function () { - var counter = chat_manager.get_needaction_counter() + chat_manager.get_chat_unread_counter(); + var counter = chat_manager.get_unread_conversation_counter(); this.$('.o_notification_counter').text(counter); this.$el.toggleClass('o_no_notification', !counter); + this.$el.toggleClass('o_unread_chat', !!chat_manager.get_chat_unread_counter()); if (this.is_open()) { this.render_channels_preview(); } @@ -52,15 +87,13 @@ var MessagingMenu = Widget.extend({ if (self.filter === 'chat') { return channel.is_chat; } else if (self.filter === 'channels') { - return !channel.is_chat && channel.type !== 'static' && !channel.mass_mailing; + return !channel.is_chat && channel.type !== 'static'; } else { - return channel.type !== 'static' && !channel.mass_mailing; + return channel.type !== 'static'; } }); - // Update inbox counter and display spinner while waiting for channels preview - var inbox_counter = chat_manager.get_needaction_counter(); - this.$('.o_inbox_counter').html(inbox_counter ? '(' + inbox_counter + ')' : ''); + // Display spinner while waiting for channels preview this.$channels_preview.html(QWeb.render('mail.chat.Spinner')); chat_manager.get_channels_preview(channels).then(function (channels_preview) { @@ -111,18 +144,6 @@ var MessagingMenu = Widget.extend({ chat_manager.bus.trigger('detach_channel', channel); } }, - on_click_redirect_to_discuss: function (event) { - event.preventDefault(); - this.discuss_redirect(); - }, - discuss_redirect: _.debounce(function () { - var self = this; - var discuss_ids = chat_manager.get_discuss_ids(); - this.do_action(discuss_ids.action_id, {clear_breadcrumbs: true}).then(function () { - self.trigger_up('hide_app_switcher'); - core.bus.trigger('change_menu_section', discuss_ids.menu_id); - }); - }, 1000, true), }); SystrayMenu.Items.push(MessagingMenu); diff --git a/addons/mail/static/src/js/thread.js b/addons/mail/static/src/js/thread.js index 439b1a8beb3..aee712ea905 100644 --- a/addons/mail/static/src/js/thread.js +++ b/addons/mail/static/src/js/thread.js @@ -38,9 +38,9 @@ var Thread = Widget.extend({ "click .oe_mail_expand": function (event) { event.preventDefault(); event.stopPropagation(); - var $source = $(event.currentTarget); - $source.parents('.o_thread_message_core').find('.o_mail_body_short').toggle(); - $source.parents('.o_thread_message_core').find('.o_mail_body_long').toggle(); + var $message = $(event.currentTarget).parents('.o_thread_message'); + $message.addClass('o_message_expanded'); + this.expanded_msg_ids.push($message.data('message-id')); }, }, @@ -55,9 +55,12 @@ var Thread = Widget.extend({ shorten_messages: true, squash_close_messages: true, }); + this.expanded_msg_ids = []; }, render: function (messages, options) { + clearTimeout(this.auto_render_timeout); + var self = this; var msgs = _.map(messages, this._preprocess_message.bind(this)); if (this.options.display_order === ORDER.DESC) { msgs.reverse(); @@ -83,6 +86,12 @@ var Thread = Widget.extend({ options: options, ORDER: ORDER, })); + + this.auto_render_timeout = setTimeout(function () { + if (!self.isDestroyed()) { + self.render(messages, options); + } + }, 1000*60); // re-render the thread every minute to update dates }, on_click_redirect: function (event) { @@ -110,7 +119,7 @@ var Thread = Widget.extend({ _preprocess_message: function (message) { var msg = _.extend({}, message); - // Set the date in the browser timezone + msg.date = moment.min(msg.date, moment()); var date = msg.date.format('YYYY-MM-DD'); if (date === moment().format('YYYY-MM-DD')) { @@ -124,7 +133,11 @@ var Thread = Widget.extend({ msg.hour = msg.date.format('LT'); } - msg.display_subject = message.subject && message.message_type !== 'notification' && !(message.model && (message.model !== 'mail.channel')); + if (_.contains(this.expanded_msg_ids, message.id)) { + msg.expanded = true; + } + + msg.display_subject = message.subject && !message.is_system_notification; return msg; }, diff --git a/addons/mail/static/src/js/window_manager.js b/addons/mail/static/src/js/window_manager.js index 65488129884..3ee3007a7ea 100644 --- a/addons/mail/static/src/js/window_manager.js +++ b/addons/mail/static/src/js/window_manager.js @@ -39,11 +39,12 @@ function open_chat (session) { var chat_session = _.findWhere(chat_sessions, {id: session.id}); if (!chat_session) { var prefix = !session.is_chat ? "#" : ""; + var options = { input_less: session.mass_mailing }; chat_session = { id: session.id, uuid: session.uuid, name: session.name, - window: new ExtendedChatWindow(web_client, session.id, prefix + session.name, session.is_folded, session.unread_counter), + window: new ExtendedChatWindow(web_client, session.id, prefix + session.name, session.is_folded, session.unread_counter, options), }; chat_session.window.on("close_chat_session", null, function () { close_chat(chat_session); |
