summaryrefslogtreecommitdiff
path: root/addons/mail/static
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-11-16 19:30:20 +0100
committerChristophe Simonis <chs@odoo.com>2018-11-16 19:30:20 +0100
commit6faad524cf5e4db02855cb213277c40aee14c42a (patch)
tree383c984dc1461a03481baa9fbdce8c156ca97e2e /addons/mail/static
parent3657dc77c2ddb4275f07d1271b93e7f25e09913a (diff)
parentbc744a1da46efda6f1eb5c341f2fa5df30c9c7ad (diff)
[MERGE] forward port branch 12.0 up to bc744a1da46
Diffstat (limited to 'addons/mail/static')
-rw-r--r--addons/mail/static/src/js/composers/basic_composer.js25
-rw-r--r--addons/mail/static/src/js/models/messages/message.js4
-rw-r--r--addons/mail/static/src/js/models/threads/channel.js5
-rw-r--r--addons/mail/static/src/js/models/threads/livechat.js5
-rw-r--r--addons/mail/static/src/js/models/threads/mailbox.js33
-rw-r--r--addons/mail/static/src/js/models/threads/thread.js7
-rw-r--r--addons/mail/static/src/js/services/mail_manager.js6
-rw-r--r--addons/mail/static/src/js/systray/systray_messaging_menu.js18
-rw-r--r--addons/mail/static/src/js/thread_windows/abstract_thread_window.js1
-rw-r--r--addons/mail/static/src/xml/discuss.xml3
-rw-r--r--addons/mail/static/tests/chatter_tests.js118
-rw-r--r--addons/mail/static/tests/discuss_moderation_tests.js80
-rw-r--r--addons/mail/static/tests/systray/systray_messaging_menu_tests.js192
-rw-r--r--addons/mail/static/tests/thread_window/basic_thread_window_tests.js75
14 files changed, 495 insertions, 77 deletions
diff --git a/addons/mail/static/src/js/composers/basic_composer.js b/addons/mail/static/src/js/composers/basic_composer.js
index a6cdb39e2de..8a533cd4515 100644
--- a/addons/mail/static/src/js/composers/basic_composer.js
+++ b/addons/mail/static/src/js/composers/basic_composer.js
@@ -211,7 +211,8 @@ var BasicComposer = Widget.extend({
* displayed to the user. If none of them match, then it will fetch for more
* partner suggestions (@see _mentionFetchPartners).
*
- * @param {$.Deferred<Object[]>} prefetchedPartners
+ * @param {$.Deferred<Object[]>} prefetchedPartners list of list of
+ * prefetched partners.
*/
mentionSetPrefetchedPartners: function (prefetchedPartners) {
this._mentionPrefetchedPartners = prefetchedPartners;
@@ -302,21 +303,23 @@ var BasicComposer = Widget.extend({
*/
_mentionFetchPartners: function (search) {
var self = this;
- return $.when(this._mentionPrefetchedPartners).then(function (partners) {
+ return $.when(this._mentionPrefetchedPartners).then(function (prefetchedPartners) {
// filter prefetched partners with the given search string
var suggestions = [];
var limit = self.options.mentionFetchLimit;
var searchRegexp = new RegExp(_.str.escapeRegExp(mailUtils.unaccent(search)), 'i');
- if (limit > 0) {
- var filteredPartners = _.filter(partners, function (partner) {
- return partner.email && searchRegexp.test(partner.email) ||
- partner.name && searchRegexp.test(mailUtils.unaccent(partner.name));
- });
- if (filteredPartners.length) {
- suggestions.push(filteredPartners.slice(0, limit));
- limit -= filteredPartners.length;
+ _.each(prefetchedPartners, function (partners) {
+ if (limit > 0) {
+ var filteredPartners = _.filter(partners, function (partner) {
+ return partner.email && searchRegexp.test(partner.email) ||
+ partner.name && searchRegexp.test(mailUtils.unaccent(partner.name));
+ });
+ if (filteredPartners.length) {
+ suggestions.push(filteredPartners.slice(0, limit));
+ limit -= filteredPartners.length;
+ }
}
- }
+ });
if (!suggestions.length && !self.options.mentionPartnersRestricted) {
// no result found among prefetched partners, fetch other suggestions
suggestions = self._mentionFetchThrottled(
diff --git a/addons/mail/static/src/js/models/messages/message.js b/addons/mail/static/src/js/models/messages/message.js
index c733b74f347..4342b1e244a 100644
--- a/addons/mail/static/src/js/models/messages/message.js
+++ b/addons/mail/static/src/js/models/messages/message.js
@@ -262,6 +262,7 @@ var Message = AbstractMessage.extend(Mixins.EventDispatcherMixin, ServicesMixin
documentID: this.getDocumentID(),
id: id,
imageSRC: this._getModuleIcon() || this.getAvatarSource(),
+ messageID: this.getID(),
status: this.status,
title: title,
};
@@ -457,6 +458,9 @@ var Message = AbstractMessage.extend(Mixins.EventDispatcherMixin, ServicesMixin
*/
setModerationStatus: function (newModerationStatus, options) {
var self = this;
+ if (newModerationStatus === this._moderationStatus) {
+ return;
+ }
this._moderationStatus = newModerationStatus;
if (newModerationStatus === 'accepted' && options) {
_.each(options.additionalThreadIDs, function (threadID) {
diff --git a/addons/mail/static/src/js/models/threads/channel.js b/addons/mail/static/src/js/models/threads/channel.js
index 695275e799e..808e8b7fbca 100644
--- a/addons/mail/static/src/js/models/threads/channel.js
+++ b/addons/mail/static/src/js/models/threads/channel.js
@@ -179,7 +179,8 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
/**
* Get listeners of a channel
*
- * @returns {$.Promise<Object[]>} resolved with list of channel listeners
+ * @returns {$.Promise<Array<Object[]>>} resolved with list of list of
+ * channel listeners.
*/
getMentionPartnerSuggestions: function () {
var self = this;
@@ -193,7 +194,7 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
})
.then(function (members) {
self._members = members;
- return members;
+ return [members];
});
}
return this._membersDef;
diff --git a/addons/mail/static/src/js/models/threads/livechat.js b/addons/mail/static/src/js/models/threads/livechat.js
index b7235e7bc0e..f4cb58ebad3 100644
--- a/addons/mail/static/src/js/models/threads/livechat.js
+++ b/addons/mail/static/src/js/models/threads/livechat.js
@@ -37,7 +37,8 @@ var Livechat = TwoUserChannel.extend({
* display of a user that is typing.
*
* @override
- * @returns {$.Promise<Object[]>} resolved with list of livechat members
+ * @returns {$.Promise<Array<Object[]>>} resolved with list of list of
+ * livechat members.
*/
getMentionPartnerSuggestions: function () {
var self = this;
@@ -49,7 +50,7 @@ var Livechat = TwoUserChannel.extend({
name: self._WEBSITE_USER_NAME,
});
}
- return self._members;
+ return [self._members];
});
},
/**
diff --git a/addons/mail/static/src/js/models/threads/mailbox.js b/addons/mail/static/src/js/models/threads/mailbox.js
index 28dbc4b7163..82d65bdd6cc 100644
--- a/addons/mail/static/src/js/models/threads/mailbox.js
+++ b/addons/mail/static/src/js/models/threads/mailbox.js
@@ -46,28 +46,6 @@ var Mailbox = SearchableThread.extend({
this._mailboxCounter = Math.max(this._mailboxCounter - num, 0);
},
/**
- * Override so that there are options to filter messages based on document
- * model and ID.
- *
- * @override
- * @param {Object} [options]
- * @param {string} [options.documentModel] model of the document that the
- * local messages of inbox must be linked to.
- * @param {integer} [options.documentID] ID of the document that the local
- * messages of inbox must be linked to.
- * @returns {mail.model.Message[]}
- */
- getMessages: function (options) {
- var messages = this._super.apply(this, arguments);
- if (options.documentModel && options.documentID) {
- return _.filter(messages, function (message) {
- return message.getDocumentModel() === options.documentModel &&
- message.getDocumentID() === options.documentID;
- });
- }
- return messages;
- },
- /**
* Get the mailbox counter of this mailbox.
*
* @returns {integer}
@@ -89,31 +67,40 @@ var Mailbox = SearchableThread.extend({
return this.fetchMessages().then(function (messages) {
// pick only last message of chatter
// items = list of objects
- // { unreadCounter: integer, message: mail.model.Message }
+ // {
+ // unreadCounter: {integer},
+ // message: {mail.model.Message},
+ // messageIDs: {integer[]},
+ // }
var items = [];
_.each(messages, function (message) {
var unreadCounter = 1;
+ var messageIDs = [message.getID()];
var similarItem = _.find(items, function (item) {
return self._areMessagesFromSameDocumentThread(item.message, message) ||
self._areMessagesFromSameChannel(item.message, message);
});
if (similarItem) {
unreadCounter = similarItem.unreadCounter + 1;
+ messageIDs = similarItem.messageIDs.concat(messageIDs);
var index = _.findIndex(items, similarItem);
items[index] = {
unreadCounter: unreadCounter,
message: message,
+ messageIDs: messageIDs
};
} else {
items.push({
unreadCounter: unreadCounter,
message: message,
+ messageIDs: messageIDs,
});
}
});
return _.map(items, function (item) {
return _.extend(item.message.getPreview(), {
unreadCounter: item.unreadCounter,
+ messageIDs: item.messageIDs,
});
});
});
diff --git a/addons/mail/static/src/js/models/threads/thread.js b/addons/mail/static/src/js/models/threads/thread.js
index c9dda28dd93..8c2beb8bbfa 100644
--- a/addons/mail/static/src/js/models/threads/thread.js
+++ b/addons/mail/static/src/js/models/threads/thread.js
@@ -15,7 +15,8 @@ var ServicesMixin = require('web.ServicesMixin');
* In particular, channels and mailboxes are two different kinds of threads.
*/
var Thread = AbstractThread.extend(ServicesMixin, {
-
+ // max number of fetched messages from the server
+ _FETCH_LIMIT: 30,
/**
* @override
* @param {Object} params
@@ -33,8 +34,6 @@ var Thread = AbstractThread.extend(ServicesMixin, {
// means that there is no message in this channel.
this._previewed = false;
this._type = params.data.type || params.data.channel_type;
- // max number of fetched messages from the server
- this._FETCH_LIMIT = 30;
},
//--------------------------------------------------------------------------
@@ -111,7 +110,7 @@ var Thread = AbstractThread.extend(ServicesMixin, {
* By default, a thread has not listener.
*
* @abstract
- * @returns {$.Promise<Object[]>}
+ * @returns {$.Promise<Array<Object[]>>}
*/
getMentionPartnerSuggestions: function () {
return $.when([]);
diff --git a/addons/mail/static/src/js/services/mail_manager.js b/addons/mail/static/src/js/services/mail_manager.js
index 734f12f0cf3..c21089b7095 100644
--- a/addons/mail/static/src/js/services/mail_manager.js
+++ b/addons/mail/static/src/js/services/mail_manager.js
@@ -199,7 +199,7 @@ var MailManager = AbstractService.extend({
* Get partners as mentions from a chatter
* Typically all employees as partner suggestions.
*
- * @returns {Array<Object[]>}
+ * @returns {Array<Array<Object[]>>}
*/
getMentionPartnerSuggestions: function () {
return this._mentionPartnerSuggestions;
@@ -1195,8 +1195,8 @@ var MailManager = AbstractService.extend({
*
* @private
* @param {Object} result data from server on mail/init_messaging rpc
- * @param {Object[]} result.mention_partner_suggestions list of suggestions
- * with all the employees
+ * @param {Array<Object[]>} result.mention_partner_suggestions list of
+ * suggestions.
* @param {integer} result.menu_id the menu ID of discuss app
*/
_updateInternalStateFromServer: function (result) {
diff --git a/addons/mail/static/src/js/systray/systray_messaging_menu.js b/addons/mail/static/src/js/systray/systray_messaging_menu.js
index 5a687131504..d86e9e3913b 100644
--- a/addons/mail/static/src/js/systray/systray_messaging_menu.js
+++ b/addons/mail/static/src/js/systray/systray_messaging_menu.js
@@ -282,7 +282,11 @@ var MessagingMenu = Widget.extend({
// e.g. needaction message of channel
var documentID = $target.data('document-id');
var documentModel = $target.data('document-model');
- this._openDocument(documentModel, documentID);
+ if (!documentModel) {
+ this._openDiscuss('mailbox_inbox');
+ } else {
+ this._openDocument(documentModel, documentID);
+ }
} else {
// preview of thread
this.call('mail_service', 'openThread', previewID);
@@ -300,19 +304,11 @@ var MessagingMenu = Widget.extend({
var thread;
var $preview = $(ev.currentTarget).closest('.o_mail_preview');
var previewID = $preview.data('preview-id');
- var documentModel = $preview.data('document-model');
if (previewID === 'mailbox_inbox') {
- var documentID = $preview.data('document-id');
- var inbox = this.call('mail_service', 'getMailbox', 'inbox');
- var messages = inbox.getMessages({
- documentModel: documentModel,
- documentID: documentID,
- });
- var messageIDs = _.map(messages, function (message) {
- return message.getID();
- });
+ var messageIDs = [].concat($preview.data('message-ids'));
this.call('mail_service', 'markMessagesAsRead', messageIDs);
} else if (previewID === 'mail_failure') {
+ var documentModel = $preview.data('document-model');
var unreadCounter = $preview.data('unread-counter');
this.do_action('mail.mail_resend_cancel_action', {
additional_context: {
diff --git a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js
index f6ba0ccecca..716b86400be 100644
--- a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js
+++ b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js
@@ -79,7 +79,6 @@ var AbstractThreadWindow = Widget.extend({
this.$header = this.$('.o_thread_window_header');
this._threadWidget = new ThreadWidget(this, {
- displayDocumentLinks: false,
displayMarkAsRead: false,
displayStars: this.options.displayStars,
});
diff --git a/addons/mail/static/src/xml/discuss.xml b/addons/mail/static/src/xml/discuss.xml
index a09b7a6f754..9d97de471ce 100644
--- a/addons/mail/static/src/xml/discuss.xml
+++ b/addons/mail/static/src/xml/discuss.xml
@@ -267,10 +267,11 @@
@param {string} [preview.title]
@param {string} [preview.status]
@param {integer} [preview.unreadCounter]
+ @param {integer[]} [preview.messageIDs]
-->
<t t-name="mail.Preview">
<div t-attf-class="o_mail_preview #{preview.unreadCounter &gt; 0 ? 'o_preview_unread' : ''}"
- t-att-data-preview-id="preview.id" t-att-data-document-id="preview.documentID" t-att-data-document-model="preview.documentModel" t-att-data-unread-counter="preview.unreadCounter">
+ t-att-data-preview-id="preview.id" t-att-data-document-id="preview.documentID" t-att-data-document-model="preview.documentModel" t-att-data-unread-counter="preview.unreadCounter" t-att-data-message-ids="preview.messageIDs">
<div t-attf-class="o_mail_preview_image #{preview.documentModel ? 'o_mail_preview_app' : ''}">
<img class="o_mail_preview_image" t-att-src="preview.imageSRC" alt="Preview"/>
<i t-if="preview.status === 'online'" class="o_mail_user_status o_user_online fa fa-circle" title="Online" role="img" aria-label="User is online"/>
diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js
index b379bc9050b..4bcce4ab352 100644
--- a/addons/mail/static/tests/chatter_tests.js
+++ b/addons/mail/static/tests/chatter_tests.js
@@ -2450,6 +2450,124 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
form.destroy();
});
+QUnit.test('chatter: mention prefetched partners (followers & employees)', function (assert) {
+ // Note: employees are in prefeteched partner for mentions in chatter when
+ // the module hr is installed.
+ assert.expect(10);
+
+ var followerSuggestions = [{
+ id: 1,
+ name: 'FollowerUser1',
+ email: 'follower-user1@example.com',
+ }, {
+ id: 2,
+ name: 'FollowerUser2',
+ email: 'follower-user2@example.com',
+ }];
+
+ var nonFollowerSuggestions = [{
+ id: 3,
+ name: 'NonFollowerUser1',
+ email: 'non-follower-user1@example.com',
+ }, {
+ id: 4,
+ name: 'NonFollowerUser2',
+ email: 'non-follower-user2@example.com',
+ }];
+
+ // link followers
+ this.data.partner.records[0].message_follower_ids = [10, 20];
+
+ // prefetched partners
+ this.data.initMessaging = {
+ mention_partner_suggestions: [followerSuggestions.concat(nonFollowerSuggestions)],
+ };
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ services: this.services,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<field name="foo"/>' +
+ '</sheet>' +
+ '<div class="oe_chatter">' +
+ '<field name="message_follower_ids" widget="mail_followers"/>' +
+ '<field name="message_ids" widget="mail_thread" options="{\'display_log_button\': True}"/>' +
+ '</div>' +
+ '</form>',
+ res_id: 2,
+ mockRPC: function (route, args) {
+ if (route === '/mail/read_followers') {
+ return $.when({
+ followers: [{
+ id: 10,
+ name: 'FollowerUser1',
+ email: 'follower-user1@example.com',
+ res_model: 'res.partner',
+ res_id: 1,
+ }, {
+ id: 20,
+ name: 'FollowerUser2',
+ email: 'follower-user2@example.com',
+ res_model: 'res.partner',
+ res_id: 2,
+ }],
+ subtypes: [],
+ });
+ }
+ if (args.method === 'message_get_suggested_recipients') {
+ return $.when({2: []});
+ }
+ if (args.method === 'get_mention_suggestions') {
+ throw new Error('should not fetch partners for mentions');
+ }
+ return this._super(route, args);
+ },
+ session: {},
+ });
+
+ assert.strictEqual(form.$('.o_followers_count').text(), '2',
+ "should have two followers of this document");
+ assert.strictEqual(form.$('.o_followers_list > .o_partner').text().replace(/\s+/g, ''),
+ 'FollowerUser1FollowerUser2',
+ "should have correct follower names");
+ assert.strictEqual(form.$('.o_composer_mention_dropdown').length, 0,
+ "should not show the mention suggestion dropdown");
+
+ form.$('.o_chatter_button_new_message').click();
+ var $input = form.$('.oe_chatter .o_composer_text_field:first()');
+ $input.val('@');
+ // the cursor position must be set for the mention manager to detect that we are mentionning
+ $input[0].selectionStart = 1;
+ $input[0].selectionEnd = 1;
+ $input.trigger('keyup');
+
+ assert.strictEqual(form.$('.o_composer_mention_dropdown').length, 1,
+ "should show the mention suggestion dropdown");
+
+ assert.strictEqual(form.$('.o_mention_proposition').length, 4,
+ "should show 4 mention suggestions");
+ assert.strictEqual(form.$('.o_mention_proposition').eq(0).text().replace(/\s+/g, ''),
+ "FollowerUser1(follower-user1@example.com)",
+ "should display correct 1st mention suggestion");
+ assert.strictEqual(form.$('.o_mention_proposition').eq(1).text().replace(/\s+/g, ''),
+ "FollowerUser2(follower-user2@example.com)",
+ "should display correct 2nd mention suggestion");
+ assert.ok(form.$('.o_mention_proposition').eq(1).next().hasClass('dropdown-divider'),
+ "should have a mention separator after last follower mention suggestion");
+ assert.strictEqual(form.$('.o_mention_proposition').eq(2).text().replace(/\s+/g, ''),
+ "NonFollowerUser1(non-follower-user1@example.com)",
+ "should display correct 3rd mention suggestion");
+ assert.strictEqual(form.$('.o_mention_proposition').eq(3).text().replace(/\s+/g, ''),
+ "NonFollowerUser2(non-follower-user2@example.com)",
+ "should display correct 4th mention suggestion");
+
+ //cleanup
+ form.destroy();
+});
+
QUnit.module('FieldMany2ManyTagsEmail', {
beforeEach: function () {
this.data = {
diff --git a/addons/mail/static/tests/discuss_moderation_tests.js b/addons/mail/static/tests/discuss_moderation_tests.js
index 51fb7b55c61..4d8e48b4dcb 100644
--- a/addons/mail/static/tests/discuss_moderation_tests.js
+++ b/addons/mail/static/tests/discuss_moderation_tests.js
@@ -1,6 +1,7 @@
odoo.define('mail.discuss_moderation_tests', function (require) {
"use strict";
+var Thread = require('mail.model.Thread');
var mailTestUtils = require('mail.testUtils');
var createDiscuss = mailTestUtils.createDiscuss;
@@ -760,5 +761,84 @@ QUnit.test('author: sent message rejected in moderated channel', function (asser
});
});
+QUnit.test('no crash when load-more fetching "accepted" message twice', function (assert) {
+ // This tests requires discuss not loading more messages due to having less
+ // messages to fetch than available height. This justifies we simply do not
+ // patch FETCH_LIMIT to 1, as it would detect that more messages could fit
+ // the empty space (it behaviour is linked to "auto load more").
+ var done = assert.async();
+ assert.expect(2);
+
+ var FETCH_LIMIT = Thread.prototype._FETCH_LIMIT;
+ // FETCH LIMIT + 30 should be enough to cover the whole available space in
+ // the thread of discuss app.
+ var messageData = [];
+ _.each(_.range(1, FETCH_LIMIT+31), function (num) {
+ messageData.push({
+ id: num,
+ body: "<p>test" + num + "</p>",
+ author_id: [100, "Someone"],
+ channel_ids: [1],
+ model: 'mail.channel',
+ res_id: 1,
+ moderation_status: 'accepted',
+ }
+ );
+ });
+
+ this.data['mail.message'].records = messageData;
+
+ this.data.initMessaging = {
+ channel_slots: {
+ channel_channel: [{
+ id: 1,
+ channel_type: "channel",
+ name: "general",
+ }],
+ },
+ };
+ var count = 0;
+
+ createDiscuss({
+ id: 1,
+ context: {},
+ params: {},
+ data: this.data,
+ services: this.services,
+ session: { partner_id: 3 },
+ mockRPC: function (route, args) {
+ if (args.method === 'message_fetch') {
+ count++;
+ if (count === 1) {
+ // inbox message_fetch
+ return $.when([]);
+ }
+ // general message_fetch
+ return $.when(messageData);
+ }
+ return this._super.apply(this, arguments);
+ },
+ })
+ .then(function (discuss) {
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.strictEqual($general.attr('title'), 'general',
+ "should have the title 'general'");
+
+ // click on general
+ $general.click();
+
+ // simulate search
+ discuss.trigger_up('search', {
+ domains: [['author_id', '=', 100]],
+ });
+
+ discuss.destroy();
+ done();
+ });
+});
+
});
});
diff --git a/addons/mail/static/tests/systray/systray_messaging_menu_tests.js b/addons/mail/static/tests/systray/systray_messaging_menu_tests.js
index 02c7ec86e6b..1b608f5c37b 100644
--- a/addons/mail/static/tests/systray/systray_messaging_menu_tests.js
+++ b/addons/mail/static/tests/systray/systray_messaging_menu_tests.js
@@ -146,8 +146,8 @@ QUnit.test('messaging menu widget: messaging menu with 1 record', function (asse
messagingMenu.destroy();
});
-QUnit.test('messaging menu widget: no crash when clicking on inbox notification not associated to a document', function (assert) {
- assert.expect(3);
+QUnit.test('messaging menu widget: open inbox for needaction not linked to any document', function (assert) {
+ assert.expect(4);
var messagingMenu = new MessagingMenu();
testUtils.addMockEnvironment(messagingMenu, {
@@ -156,17 +156,6 @@ QUnit.test('messaging menu widget: no crash when clicking on inbox notification
session: {
partner_id: 1,
},
- intercepts: {
- /**
- * Simulate action 'mail.action_discuss' successfully performed.
- *
- * @param {OdooEvent} ev
- * @param {function} ev.data.on_success called when success action performed
- */
- do_action: function (ev) {
- ev.data.on_success();
- },
- },
});
messagingMenu.appendTo($('#qunit-fixture'));
@@ -195,12 +184,18 @@ QUnit.test('messaging menu widget: no crash when clicking on inbox notification
assert.strictEqual($firstChannelPreview.data('preview-id'),
'mailbox_inbox',
"should be a preview from channel inbox");
- try {
- $firstChannelPreview.click();
- assert.ok(true, "should not have crashed when clicking on needaction preview message");
- } finally {
- messagingMenu.destroy();
- }
+
+ testUtils.intercept(messagingMenu, 'do_action', function (ev) {
+ if (ev.data.action === 'mail.action_discuss') {
+ assert.step('do_action:' + ev.data.action + ':' + ev.data.options.active_id);
+ }
+ }, true);
+ $firstChannelPreview.click();
+ assert.verifySteps(
+ ['do_action:mail.action_discuss:mailbox_inbox'],
+ "should open Discuss with Inbox");
+
+ messagingMenu.destroy();
});
QUnit.test("messaging menu widget: mark as read on thread preview", function ( assert ) {
@@ -432,5 +427,164 @@ QUnit.test('update messaging preview on receiving a new message in channel previ
messagingMenu.destroy();
});
+QUnit.test('preview of inbox message not linked to document + mark as read', function (assert) {
+ assert.expect(17);
+
+ this.data.initMessaging = {
+ needaction_inbox_counter: 2,
+ };
+
+ var needactionMessages = [{
+ author_id: [1, "Demo"],
+ body: "<p>*Message1*</p>",
+ id: 689,
+ needaction: true,
+ needaction_partner_ids: [44],
+ }, {
+ author_id: [1, "Demo"],
+ body: "<p>*Message2*</p>",
+ id: 690,
+ needaction: true,
+ needaction_partner_ids: [44],
+ }];
+ this.data['mail.message'].records =
+ this.data['mail.message'].records.concat(needactionMessages);
+
+ var messagingMenu = new MessagingMenu();
+ testUtils.addMockEnvironment(messagingMenu, {
+ services: this.services,
+ data: this.data,
+ session: {
+ partner_id: 44,
+ },
+ mockRPC: function (route, args) {
+ if (args.method === 'set_message_done') {
+ assert.step({
+ method: 'set_message_done',
+ messageIDs: args.args[0],
+ });
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+ messagingMenu.appendTo($('#qunit-fixture'));
+ assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '2',
+ "should display a counter of 2 on the messaging menu icon");
+
+ messagingMenu.$('.dropdown-toggle').click();
+
+ assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 2,
+ "should display two previews");
+
+ var $preview1 = messagingMenu.$('.o_mail_preview').eq(0);
+ var $preview2 = messagingMenu.$('.o_mail_preview').eq(1);
+
+ assert.strictEqual($preview1.data('preview-id'),
+ "mailbox_inbox",
+ "1st preview should be from the mailbox inbox");
+ assert.strictEqual($preview2.data('preview-id'),
+ "mailbox_inbox",
+ "2nd preview should also be from the mailbox inbox");
+ assert.ok($preview1.hasClass('o_preview_unread'),
+ "1st preview should be marked as unread");
+ assert.ok($preview2.hasClass('o_preview_unread'),
+ "2nd preview should also be marked as unread");
+ assert.strictEqual($preview1.find('.o_last_message_preview').text().replace(/\s/g, ''),
+ "Demo:*Message1*", "should correctly display the 1st preview");
+ assert.strictEqual($preview2.find('.o_last_message_preview').text().replace(/\s/g, ''),
+ "Demo:*Message2*", "should correctly display the 2nd preview");
+
+ $preview1.find('.o_mail_preview_mark_as_read').click();
+ assert.verifySteps([{
+ method: 'set_message_done',
+ messageIDs: [689],
+ }], "should mark 1st preview as read");
+ assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '1',
+ "should display a counter of 1 on the messaging menu icon after marking one preview as read");
+ assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 1,
+ "should display a single preview remaining");
+ assert.strictEqual(messagingMenu.$('.o_mail_preview .o_last_message_preview').text().replace(/\s/g, ''),
+ "Demo:*Message2*", "preview 2 should be the remaining one");
+
+ $preview2 = messagingMenu.$('.o_mail_preview');
+ $preview2.find('.o_mail_preview_mark_as_read').click();
+ assert.verifySteps([{
+ method: 'set_message_done',
+ messageIDs: [689],
+ }, {
+ method: 'set_message_done',
+ messageIDs: [690],
+ }], "should mark 2nd preview as read");
+ assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '0',
+ "should display a counter of 0 on the messaging menu icon after marking both previews as read");
+ assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 0,
+ "should display no preview remaining");
+
+ messagingMenu.destroy();
+});
+
+QUnit.test('grouped preview for needaction messages linked to same document', function (assert) {
+ assert.expect(5);
+
+ // simulate two (read) needaction (mention) messages in channel 'general'
+ var needactionMessage1 = {
+ author_id: [1, "Demo"],
+ body: "<p>@Administrator: ping</p>",
+ channel_ids: [1],
+ id: 3,
+ model: 'mail.channel',
+ needaction: true,
+ needaction_partner_ids: [44],
+ record_name: 'general',
+ res_id: 1,
+ };
+ var needactionMessage2 = {
+ author_id: [2, "Other"],
+ body: "<p>@Administrator: pong</p>",
+ channel_ids: [1],
+ id: 4,
+ model: 'mail.channel',
+ needaction: true,
+ needaction_partner_ids: [44],
+ record_name: 'general',
+ res_id: 1,
+ };
+ this.data['mail.message'].records = [needactionMessage1, needactionMessage2];
+ this.data.initMessaging.channel_slots.channel_channel[0].message_unread_counter = 0;
+ this.data.initMessaging.needaction_inbox_counter = 2;
+
+ var messagingMenu = new MessagingMenu();
+ testUtils.addMockEnvironment(messagingMenu, {
+ services: this.services,
+ data: this.data,
+ session: {
+ partner_id: 44,
+ },
+ });
+ messagingMenu.appendTo($('#qunit-fixture'));
+
+ messagingMenu.$('.dropdown-toggle').click();
+ var $previews = messagingMenu.$('.o_mail_preview');
+
+ assert.strictEqual($previews.length, 2,
+ "should display two previews (one for needaction, one for channel)");
+
+ var $needactionPreview = $previews.eq(0);
+ var $channelPreview = $previews.eq(1);
+
+ assert.strictEqual($needactionPreview.find('.o_preview_counter').text().trim(), "(2)",
+ "should show two needaction messages in the needaction preview");
+ assert.strictEqual($needactionPreview.find('.o_last_message_preview').text().replace(/\s/g, ""),
+ "Other:@Administrator:pong",
+ "should display last needaction message on needaction preview");
+ assert.strictEqual($channelPreview.find('.o_preview_counter').text().trim(), "",
+ "should show no unread messages in the channel preview");
+ assert.strictEqual($channelPreview.find('.o_last_message_preview').text().replace(/\s/g, ""),
+ "Other:@Administrator:pong",
+ "should display last needaction message on channel preview");
+
+ messagingMenu.destroy();
+});
+
});
});
diff --git a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js
index f05fd367697..4b8935e81cf 100644
--- a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js
+++ b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js
@@ -353,6 +353,81 @@ QUnit.test('do not mark as read the newly open thread window from received messa
parent.destroy();
});
+QUnit.test('show document link of message linked to a document', function (assert) {
+ assert.expect(6);
+
+ this.data['mail.channel'] = {
+ fields: {
+ name: {
+ string: "Name",
+ type: "char",
+ required: true,
+ },
+ channel_type: {
+ string: "Channel Type",
+ type: "selection",
+ },
+ channel_message_ids: {
+ string: "Messages",
+ type: "many2many",
+ relation: 'mail.message'
+ },
+ message_unread_counter: {
+ string: "Amount of Unread Messages",
+ type: "integer"
+ },
+ },
+ records: [{
+ id: 2,
+ name: "R&D Tasks",
+ channel_type: "channel",
+ }],
+ };
+ this.data['mail.message'].records.push({
+ author_id: [5, "Someone else"],
+ body: "<p>Test message</p>",
+ id: 40,
+ model: 'some.document',
+ record_name: 'Some Document',
+ res_id: 10,
+ channel_ids: [2],
+ });
+
+ this.data.initMessaging.channel_slots.channel_channel.push({
+ id: 2,
+ name: "R&D Tasks",
+ channel_type: "public",
+ });
+
+ var parent = this.createParent({
+ data: this.data,
+ services: this.services,
+ session: { partner_id: 3 },
+ });
+
+ assert.strictEqual($('.o_thread_window').length, 0,
+ "no thread window should be open initially");
+
+ // get channel instance to link to thread window
+ var channel = parent.call('mail_service', 'getChannel', 2);
+ channel.detach();
+
+ var $threadWindow = $('.o_thread_window');
+ assert.strictEqual($threadWindow.length, 1,
+ "a thread window should be open");
+ assert.strictEqual($threadWindow.find('.o_thread_window_title').text().trim(),
+ "#R&D Tasks",
+ "should be thread window of correct channel");
+ assert.strictEqual($threadWindow.find('.o_thread_message').length, 1,
+ "should contain a single message in thread window");
+ assert.ok($threadWindow.find('.o_mail_info').text().replace(/\s/g, "").indexOf('Someoneelse') !== -1,
+ "message should be from 'Someone else' user");
+ assert.ok($threadWindow.find('.o_mail_info').text().replace(/\s/g, "").indexOf('onSomeDocument') !== -1,
+ "message should link to 'Some Document'");
+
+ parent.destroy();
+});
+
});
});
});