[MERGE][FIX] mail: several discuss and messaging menu fixes

This merge fixes the following issues

1.  No prefix '#' on DM chats
2. Undated previews appear last in the messaging menu

It also adds a missing test for "[FIX] mail: add mention no set focus on subject" https://github.com/odoo/odoo/commit/6d5df714a7970f69a27296c157b08772ceac5b7d.

Task-ID 1911738
Task-ID 1912001

closes odoo/odoo#28926
This commit is contained in:
Robot Odoo
2018-11-26 10:51:39 +01:00
committed by GitHub
7 changed files with 165 additions and 23 deletions
+1 -1
View File
@@ -852,7 +852,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
// Update control panel before focusing the composer, otherwise
// focus is on the searchview
self.set("title", '#' + self._thread.getName());
self.set("title", self._thread.getTitle());
self._updateControlPanel();
self._updateControlPanelButtons(self._thread);
@@ -217,20 +217,10 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
return _.extend(result, {
author: lastMessage ? lastMessage.getDisplayedAuthor() : '',
body: lastMessage ? mailUtils.parseAndTransform(lastMessage.getBody(), mailUtils.inline) : '',
date: lastMessage ? lastMessage.getDate() : moment(),
date: lastMessage ? lastMessage.getDate() : undefined,
isMyselfAuthor: this.hasMessages() && this.getLastMessage().isMyselfAuthor(),
});
},
/**
* Returns the title to display in thread window's headers.
* For channels, the title is prefixed with "#".
*
* @override
* @returns {string|Object} the name of the thread by default (see getName)
*/
getTitle: function () {
return "#" + this._super.apply(this, arguments);
},
/**
* Get the UUID of the channel.
* This is a string that uniquely links this channel to a server channel.
@@ -25,6 +25,16 @@ var MultiUserChannel = Channel.extend({
// Public
//--------------------------------------------------------------------------
/**
* Returns the title to display in thread window's headers.
* For channels, the title is prefixed with "#".
*
* @override
* @returns {string|Object} the name of the thread by default (see getName)
*/
getTitle: function () {
return "#" + this._super.apply(this, arguments);
},
/**
* States whether this thread has the mass mailing setting active or not.
* This is a server-side setting, that determine the type of composer that
@@ -1108,8 +1108,9 @@ var MailManager = AbstractService.extend({
* Sort previews
*
* 1. unread,
* 2. two-user thread,
* 3. date,
* 2. dated previews
* 3. two-user thread,
* 4. date,
*
* @private
* @param {Object[]} previews
@@ -1118,13 +1119,10 @@ var MailManager = AbstractService.extend({
_sortPreviews: function (previews) {
var res = previews.sort(function (p1, p2) {
var unreadDiff = Math.min(1, p2.unreadCounter) - Math.min(1, p1.unreadCounter);
var datedDiff = !!p2.date - !!p1.date;
var isTwoUserThreadDiff = p2.isTwoUserThread - p1.isTwoUserThread;
var dateDiff = (!!p2.date - !!p1.date) ||
(
p2.date &&
p2.date.diff(p1.date)
);
return unreadDiff || isTwoUserThreadDiff || dateDiff;
var dateDiff = p2.date && p2.date.diff(p1.date);
return unreadDiff || datedDiff || isTwoUserThreadDiff || dateDiff;
});
return res;
},
+79
View File
@@ -513,6 +513,85 @@ QUnit.test('@ mention with special chars', function (assert) {
});
});
QUnit.test('@ mention in mailing channel', function (assert) {
assert.expect(8);
var done = assert.async();
var fetchListenersDef = $.Deferred();
this.data.initMessaging = {
channel_slots: {
channel_channel: [{
id: 1,
channel_type: "channel",
name: "general",
mass_mailing: true,
}],
},
};
createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
fetchListenersDef.resolve();
return $.when([
{id: 1, name: 'Admin'},
]);
}
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]');
// click on general
$general.click();
// 1st composer: basic composer (hidden), 2nd composer: extended (shown)
var $input = discuss.$('textarea.o_composer_text_field').eq(1);
assert.ok($input.length, "should display a composer input");
// Simulate '@' typed by user with mocked Window.getSelection
// Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
$input.focus();
$input.val("@");
$input.trigger('keyup');
fetchListenersDef
.then(concurrency.delay.bind(concurrency, 0))
.then(function () {
assert.strictEqual(discuss.$('.dropup.o_composer_mention_dropdown.show').length, 1,
"dropup menu for partner mentions should be open");
var $mention = discuss.$('.o_mention_proposition');
assert.strictEqual($mention.length, 1,
"should display 1 partner mention proposition");
// correct mention proposition
assert.ok($mention.hasClass('active'),
"partner mention should be active");
assert.strictEqual($mention.data('id'), 1,
"partner mention should link to the correct partner id");
assert.strictEqual($mention.find('.o_mention_name').text(), "Admin",
"partner mention should display the correct partner name");
// equivalent to $mentionPropositions.find('active').click();
$input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
assert.ok($input.is(':focus'), "composer body should have focus");
assert.notOk(discuss.$('.o_composer_subject').is(':focus'));
discuss.destroy();
done();
});
});
});
QUnit.test('no crash focusout emoji button', function (assert) {
assert.expect(3);
var done = assert.async();
@@ -625,5 +625,70 @@ QUnit.test("messaging menu widget: channel seen notification", function ( assert
messagingMenu.destroy();
});
QUnit.test("messaging menu widget: preview with no message should be undated", function ( assert ) {
assert.expect(2);
// remove any message on the channel
this.data['mail.channel'].records[0].channel_message_ids = [];
this.data['mail.message'].records[0].channel_ids = [];
var messagingMenu = new MessagingMenu();
testUtils.addMockEnvironment(messagingMenu, {
services: this.services,
data: this.data,
});
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 1,
"should have two previews in messaging menu");
assert.ok(_.isEmpty(messagingMenu.$('.o_mail_preview .o_last_message_date').text().trim()),
"should have preview as undated");
messagingMenu.destroy();
});
QUnit.test("messaging menu widget: sort dated previews before undated previews", function ( assert ) {
assert.expect(5);
var dm = {
id: 2,
name: "DM",
channel_type: "chat",
};
this.data['mail.channel'].records.push(dm);
this.data.initMessaging.channel_slots.direct_message = [dm];
var messagingMenu = new MessagingMenu();
testUtils.addMockEnvironment(messagingMenu, {
services: this.services,
data: this.data,
});
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 2,
"should have two previews in messaging menu");
var $preview1 = messagingMenu.$('.o_mail_preview').eq(0);
var $preview2 = messagingMenu.$('.o_mail_preview').eq(1);
assert.strictEqual($preview1.data('preview-id'), 1,
"should have channel preview as the 1st preview (dated preview)");
assert.notOk(_.isEmpty($preview1.find('.o_last_message_date').text().trim()),
"should have channel preview as dated");
assert.strictEqual($preview2.data('preview-id'), 2,
"should have DM preview as the 1st preview (non-dated preview)");
assert.ok(_.isEmpty($preview2.find('.o_last_message_date').text().trim()),
"should have DM preview as undated");
messagingMenu.destroy();
});
});
});
@@ -229,7 +229,7 @@ QUnit.test('open new DM chat from blank thread window', function (assert) {
selectDef.then(function () {
assert.strictEqual($('.o_thread_window').length, 1,
"should be a single window");
assert.strictEqual($('.o_thread_window_title').text().trim(), "#DemoUser1",
assert.strictEqual($('.o_thread_window_title').text().trim(), "DemoUser1",
"should have thread window of the DM chat with 'DemoUser1'");
assert.strictEqual($('.o_composer_text_field').length, 1,
"should have a composer in the DM chat window");
@@ -285,7 +285,7 @@ QUnit.test('open already detached DM chat from blank thread window', function (a
assert.strictEqual($('.o_thread_window').length, 1,
"should be a single window");
assert.strictEqual($('.o_thread_window_title').text().trim(), "#DemoUser1",
assert.strictEqual($('.o_thread_window_title').text().trim(), "DemoUser1",
"should have thread window of the DM chat with 'DemoUser1'");
assert.strictEqual($('.o_composer_text_field').length, 1,
"should have a composer in the DM chat window");
@@ -304,7 +304,7 @@ QUnit.test('open already detached DM chat from blank thread window', function (a
selectDef.then(function () {
assert.strictEqual($('.o_thread_window').length, 1,
"should now have a single thread window open");
assert.strictEqual($('.o_thread_window_title').text().trim(), "#DemoUser1",
assert.strictEqual($('.o_thread_window_title').text().trim(), "DemoUser1",
"the remaining thread window should be the DM chat with 'DemoUser1'");
self.unpatchAutocomplete();