diff options
| author | Alexandre Kühn <aku@odoo.com> | 2018-07-04 15:57:03 +0200 |
|---|---|---|
| committer | Alexandre Kühn <aku@odoo.com> | 2018-07-19 13:58:34 +0200 |
| commit | 915da49d173e9ab8d0c6d94cbeec124c83d23fc7 (patch) | |
| tree | d7fe30d4a4c7f1a6923b88c91ac98582ee6500f4 /addons/mail/static/src/js/models | |
| parent | ec8c505bc1c9ec21939e9ffef53a9cc6f63f30c7 (diff) | |
[IMP] mail, *: template rendering with abstract thread, adapt thread instantiation, thread `getMessages`/`fetchMessages`, and create mode document thread.
* = im_livechat, im_support
- thread widget now uses abstract thread in `render` method
- thread models have their `init` parameters changed, so that the parent may be optional
- reworked 'creating a new record...' in chatter in create mode:
> new model CreateModeDocumentThread, which basically is a fake document thread
with a fake message for its rendering in create mode of the chatter
> special rendering method of thread_widget for such case: `renderChatterCreateMode`
- renamed thread methods previously named `getMessages` to `fetchMessages`:
> in order to not conflict with `getMessages`, used for rendering
> now, `getMessages` always get messages that are locally,
while `fetchMessages` may fetch messages.
TODO:
- special thread model for im_livechat (rendering is broken ATM)
Diffstat (limited to 'addons/mail/static/src/js/models')
9 files changed, 223 insertions, 117 deletions
diff --git a/addons/mail/static/src/js/models/messages/abstract_message.js b/addons/mail/static/src/js/models/messages/abstract_message.js index 6c5f247386f..420ac2da41b 100644 --- a/addons/mail/static/src/js/models/messages/abstract_message.js +++ b/addons/mail/static/src/js/models/messages/abstract_message.js @@ -44,8 +44,6 @@ var AbstractMessage = Class.extend({ this._id = data.id; this._isDiscussion = data.is_discussion; this._isNotification = data.is_notification; - // if set, the message should display the author of the message - this._displayAuthor = false; this._serverAuthorID = data.author_id; this._type = data.message_type || undefined; @@ -268,12 +266,12 @@ var AbstractMessage = Class.extend({ return this._isDiscussion; }, /** - * State whether this message is linked to a document - * By default, messages are not linked to a document. + * State whether this message is linked to a document thread + * By default, messages are not linked to a document thread. * * @return {boolean} */ - isLinkedToDocument: function () { + isLinkedToDocumentThread: function () { return false; }, /** @@ -338,14 +336,6 @@ var AbstractMessage = Class.extend({ return false; }, /** - * State whether this message should display the author - * - * @return {boolean} - */ - shouldDisplayAuthor: function () { - return this._displayAuthor; - }, - /** * State whether this message should redirect to the author * when clicking on the author of this message. * diff --git a/addons/mail/static/src/js/models/threads/abstract_thread.js b/addons/mail/static/src/js/models/threads/abstract_thread.js index 3ea263fa996..788a04307a7 100644 --- a/addons/mail/static/src/js/models/threads/abstract_thread.js +++ b/addons/mail/static/src/js/models/threads/abstract_thread.js @@ -6,15 +6,42 @@ var Class = require('web.Class'); /** * Abstract thread is the super class of all threads, either backend threads * (which are compatible with mail service) or website livechats. + * + * Abstract threads contain abstract messages */ var AbstractThread = Class.extend({ - init: function (parent, data) {}, + /** + * @param {Object} params + * @param {Object} params.data + * @param {Object} params.data.id the ID of this thread + */ + init: function (params) { + this._id = params.data.id; + }, //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- + /** + * Get the ID of this thread + * + * @returns {integer|string} + */ + getID: function () { + return this._id; + }, + /** + * @abstract + * @returns {mail.model.AbstractMessage[]} + */ getMessages: function () {}, + /** + * @returns {boolean} + */ + hasMessages: function () { + return !_.isEmpty(this.getMessages()); + }, }); return AbstractThread; diff --git a/addons/mail/static/src/js/models/threads/channel.js b/addons/mail/static/src/js/models/threads/channel.js index e63cab2f907..86482a71a6d 100644 --- a/addons/mail/static/src/js/models/threads/channel.js +++ b/addons/mail/static/src/js/models/threads/channel.js @@ -17,30 +17,35 @@ var time = require('web.time'); var Channel = ThreadWithCache.extend({ /** * @override - * @param {string} [data.anonymous_name] - * @param {string} data.channel_type - * @param {boolean} data.group_based_subscription - * @param {boolean} [data.is_minimized=false] - * @param {boolean} data.is_moderator whether the current user is + * @param {Object} params + * @param {Object} params.data + * @param {string} [params.data.anonymous_name] + * @param {string} params.data.channel_type + * @param {boolean} params.data.group_based_subscription + * @param {boolean} [params.data.is_minimized=false] + * @param {boolean} params.data.is_moderator whether the current user is * moderator of this channel. - * @param {string} [data.last_message_date] date in server-format - * @param {boolean} [data.mass_mailing] - * @param {integer} [data.message_unread_counter] - * @param {string} [data.public] either 'public' or 'private' - * @param {string} data.state - * @param {string} [data.uuid] - * @param {Object} options - * @param {boolean} [options.autoswitch=true] - * @param {Object[]} commands + * @param {string} [params.data.last_message_date] date in server-format + * @param {boolean} [params.data.mass_mailing] + * @param {integer} [params.data.message_unread_counter] + * @param {string} [params.data.public] either 'public' or 'private' + * @param {string} params.data.state + * @param {string} [params.data.uuid] + * @param {Object} params.options + * @param {boolean} [params.options.autoswitch=true] + * @param {Object[]} params.commands */ - init: function (parent, data, options, commands) { + init: function (params) { var self = this; this._super.apply(this, arguments); + var data = params.data; + var options = params.options; + var commands = params.commands; + // If set, autoswitch channel on joining this channel in discuss // the default behaviour is to autoswitch on join. // exception: receiving channel or chat session notifications - // this._autoswitch = 'autoswitch' in options ? options.autoswitch : true; this._chat = undefined; // FIXME: could be dropped when livechat and DM are moved out of this class this._commands = undefined; diff --git a/addons/mail/static/src/js/models/threads/create_mode_document_thread.js b/addons/mail/static/src/js/models/threads/create_mode_document_thread.js new file mode 100644 index 00000000000..ab396984b54 --- /dev/null +++ b/addons/mail/static/src/js/models/threads/create_mode_document_thread.js @@ -0,0 +1,75 @@ +odoo.define('mail.model.CreateModeDocumentThread', function (require) { +"use strict"; + +var AbstractMessage = require('mail.model.AbstractMessage'); +var AbstractThread = require('mail.model.AbstractThread'); + +var core = require('web.core'); +var session = require('web.session'); + +var _t = core._t; + +/** + * Special document thread that is linked to a new document that is in create + * mode. This thread only display a single (fake) message which displays the + * user avatar and the message 'creating a new record...'. + * + * Note: it uses AbstractThread and AbstractMessage, because this is a fake + * thread which contains a fake message. We do not want to register both of them + * in the mail service. + */ +var CreateModeDocumentThread = AbstractThread.extend({ + + /** + * @override + */ + init: function () { + var params = { + data: { + id: '_createModeDocumentThread' + } + }; + + this._super(params); + + this._messages = this._forgeCreateMessages(); + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * @returns {mail.model.AbstractMessage[]} + */ + getMessages: function () { + return this._messages; + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Make a fake list of messages to render in create mode. + * Instead of rendering no messages at all, it displays a single message + * with body content "Creating a new record". + * + * @private + * @returns {mail.model.AbstractMessage[]} an array containing a single + * message 'Creating a new record...' + */ + _forgeCreateMessages: function () { + var createMessage = new AbstractMessage(this, { + id: 0, + body: _t("<p>Creating a new record...</p>"), + author_id: [session.partner_id, session.partner_display_name], + }); + return [createMessage]; + }, + +}); + +return CreateModeDocumentThread; + +}); diff --git a/addons/mail/static/src/js/models/threads/dm.js b/addons/mail/static/src/js/models/threads/dm.js index cd08dd7526d..dc24681990b 100644 --- a/addons/mail/static/src/js/models/threads/dm.js +++ b/addons/mail/static/src/js/models/threads/dm.js @@ -11,15 +11,18 @@ var Channel = require('mail.model.Channel'); var DM = Channel.extend({ /** * @override - * @param {Object} data - * @param {Object} data.direct_partner - * @param {integer} data.direct_partner[0].id - * @param {string} data.direct_partner[0].im_status - * @param {string} data.direct_partner[0].name + * @param {Object} params + * @param {Object} params.data + * @param {Object} params.data.direct_partner + * @param {integer} params.data.direct_partner[0].id + * @param {string} params.data.direct_partner[0].im_status + * @param {string} params.data.direct_partner[0].name */ - init: function (parent, data) { + init: function (params) { this._super.apply(this, arguments); + var data = params.data; + this._type = 'dm'; this._name = data.direct_partner[0].name; this._directPartnerID = data.direct_partner[0].id; diff --git a/addons/mail/static/src/js/models/threads/document_thread.js b/addons/mail/static/src/js/models/threads/document_thread.js index 92cc26e845b..cf3e27c8c81 100644 --- a/addons/mail/static/src/js/models/threads/document_thread.js +++ b/addons/mail/static/src/js/models/threads/document_thread.js @@ -24,13 +24,16 @@ var DocumentThread = Thread.extend({ /** * @override - * @param {string} [data.messagesIDs] the list of message ids linked + * @param {Object} params + * @param {Object} params.data + * @param {string} [params.data.messagesIDs] the list of message ids linked * to the document (if not given, they will be fetched before fetching the * messages) - * @param {string} data.model - * @param {integer} data.resID + * @param {string} params.data.model + * @param {integer} params.data.resID */ - init: function (parent, data) { + init: function (params) { + var data = params.data; data.id = data.resModel + '_' + data.resID; data.type = 'document_thread'; @@ -99,6 +102,23 @@ var DocumentThread = Thread.extend({ }); }, /** + * + * Fetch messages of the document thread + * + * @override + * @param {Object} options + * @param {boolean} [options.forceFetch] if true, fetch anyway, as user + * clicked on 'load more'. + * @returns {$.Promise<mail.model.Message[]>} + */ + fetchMessages: function (options) { + var self = this; + return this._fetchMessages(options).then(function () { + self.call('mail_service', 'markMessagesAsRead', self._messageIDs); + return self._messages; + }); + }, + /** * Overrides to store the thread's state in the LocalStorage, so that it is * shared between tabs, and restored on F5. * @@ -137,21 +157,11 @@ var DocumentThread = Thread.extend({ return this._messageIDs; }, /** - * - * Get messages of the document thread - * * @override - * @param {Object} options - * @param {boolean} [options.forceFetch] if true, fetch anyway, as user - * clicked on 'load more'. - * @returns {$.Promise<mail.model.Message[]>} + * @returns {mail.model.Message[]} */ - getMessages: function (options) { - var self = this; - return this._fetchMessages(options).then(function () { - self.call('mail_service', 'markMessagesAsRead', self._messageIDs); - return self._messages; - }); + getMessages: function () { + return this._messages; }, /** * States whether the thread is linked to a document diff --git a/addons/mail/static/src/js/models/threads/mailbox.js b/addons/mail/static/src/js/models/threads/mailbox.js index bcb5ae609b7..6d2e75c59b1 100644 --- a/addons/mail/static/src/js/models/threads/mailbox.js +++ b/addons/mail/static/src/js/models/threads/mailbox.js @@ -18,13 +18,15 @@ var Mailbox = ThreadWithCache.extend({ /** * @override - * @param {Object} data - * @param {string} data.id the ID of the mailbox, without the 'mailbox_' - * prefix. - * @param {integer} [data.mailboxCounter=0] the initial mailbox counter of - * this mailbox. + * @param {Object} params + * @param {Object} params.data + * @param {string} params.data.id the ID of the mailbox, without the + * 'mailbox_' prefix. + * @param {integer} [params.data.mailboxCounter=0] the initial mailbox + * counter of this mailbox. */ - init: function (parent, data) { + init: function (params) { + var data = params.data; // ID or mailboxes are always prefixed with 'mailbox_' data.id = 'mailbox_' + data.id; data.type = 'mailbox'; @@ -89,7 +91,7 @@ var Mailbox = ThreadWithCache.extend({ getMessagePreviews: function () { var self = this; - return this.getMessages().then(function (messages) { + return this.fetchMessages().then(function (messages) { // pick only last message of chatter // items = list of objects // { unreadCounter: integer, message: mail.model.Message } diff --git a/addons/mail/static/src/js/models/threads/thread.js b/addons/mail/static/src/js/models/threads/thread.js index de2c6628d67..5a376f8f7e2 100644 --- a/addons/mail/static/src/js/models/threads/thread.js +++ b/addons/mail/static/src/js/models/threads/thread.js @@ -2,9 +2,9 @@ odoo.define('mail.model.Thread', function (require) { "use strict"; var emojis = require('mail.emojis'); +var AbstractThread = require('mail.model.AbstractThread'); var mailUtils = require('mail.utils'); -var Class = require('web.Class'); var Mixins = require('web.mixins'); var ServicesMixin = require('web.ServicesMixin'); @@ -15,20 +15,20 @@ var ServicesMixin = require('web.ServicesMixin'); * * In particular, channels and mailboxes are two different kinds of threads. */ -var Thread = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { - /** - * @param {mail.Manager} parent - * @param {Object} data - * @param {string} [data.channel_type] - * @param {integer|string} data.id - * @param {string} data.name - * @param {string} [data.type] - */ - init: function (parent, data) { +var Thread = AbstractThread.extend(Mixins.EventDispatcherMixin, ServicesMixin, { + /** + * @override + * @param {Object} params + * @param {mail.Manager} param.parent + * @param {Object} params.data + * @param {string} [params.data.channel_type] + * @param {string} params.data.name + * @param {string} [params.data.type] + */ + init: function (params) { + this._super.apply(this, arguments); Mixins.EventDispatcherMixin.init.call(this, arguments); - this.setParent(parent); - - this._id = data.id; + this.setParent(params.parent); // threads are not detached by default this._detached = false; @@ -38,11 +38,11 @@ var Thread = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { // extended composer and show "Send by messages by email" on discuss // sidebar this._massMailing = false; - this._name = data.name; + this._name = params.data.name; // on 1st request to getPreview, fetch data if incomplete. Otherwise it // means that there is no message in this channel. this._previewed = false; - this._type = data.type || data.channel_type; + this._type = params.data.type || params.data.channel_type; // any new message that has not been read yet this._unreadCounter = 0; // max number of fetched messages from the server @@ -88,6 +88,23 @@ var Thread = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { }); }, /** + * Fetch the list of messages in this thread. + * By default, a thread has no messages. + * + * Note that this method only returns some messages, as we do not want to + * fetch all messages of a thread at once, just to read the last message. + * + * As a result, this method fetches only some messages of the thread, + * starting from the last message in the thread. At most, it fetches + * `this.LIMIT` number of messages at a time. + * + * @abstract + * @returns {$.Promise<mail.model.Message[]>} + */ + fetchMessages: function () { + return $.when([]); + }, + /** * Updates the _folded state of the thread. Must be overriden to reflect * the new state in the interface. */ @@ -106,14 +123,6 @@ var Thread = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { return []; }, /** - * Get the ID of the thread - * - * @returns {integer|string} string for mailboxes (e.g. 'mailbox_inbox') - */ - getID: function () { - return this._id; - }, - /** * Get the listeners of the thread. * By default, a thread has not listener. * @@ -124,23 +133,6 @@ var Thread = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { return $.when([]); }, /** - * Get the list of messages in this thread. - * By default, a thread has no messages. - * - * Note that this method only returns some messages, as we do not want to - * fetch all messages of a thread at once, just to read the last message. - * - * As a result, this method fetches only some messages of the thread, - * starting from the last message in the thread. At most, it fetches - * `this.LIMIT` number of messages at a time. - * - * @abstract - * @returns {$.Promise<mail.model.Message[]>} - */ - getMessages: function () { - return $.when([]); - }, - /** * Get the name of this thread * * @returns {string|Object} object for lazy translated names with _lt diff --git a/addons/mail/static/src/js/models/threads/thread_with_cache.js b/addons/mail/static/src/js/models/threads/thread_with_cache.js index f25a19005f2..ef064072bbf 100644 --- a/addons/mail/static/src/js/models/threads/thread_with_cache.js +++ b/addons/mail/static/src/js/models/threads/thread_with_cache.js @@ -16,9 +16,11 @@ var session = require('web.session'); var ThreadWithCache = Thread.extend({ /** * @override - * @param {integer} [data.seen_message_id=undefined] + * @param {Object} params + * @param {Object} params.data + * @param {integer} [params.data.seen_message_id=undefined] */ - init: function (parent, data) { + init: function (params) { this._super.apply(this, arguments); this._cache = { @@ -28,7 +30,7 @@ var ThreadWithCache = Thread.extend({ messages: [], } }; - this._lastSeenMessageID = data.seen_message_id; + this._lastSeenMessageID = params.data.seen_message_id; }, //-------------------------------------------------------------------------- @@ -53,19 +55,11 @@ var ThreadWithCache = Thread.extend({ } }, /** - * Get the last seen message for a given thread - * - * @return {integer|null} last seen message ID (if any) - */ - getLastSeenMessageID: function () { - return this._lastSeenMessageID || null; - }, - /** * @override * @param {Array} [domain] * @param {boolean} [loadMore=false] */ - getMessages: function (domain, loadMore) { + fetchMessages: function (domain, loadMore) { if (loadMore) { return this._fetchMessages(domain, true); } @@ -77,11 +71,19 @@ var ThreadWithCache = Thread.extend({ } }, /** - * @private - * @return {boolean} true if there is at least a message, false otherwise + * Get the last seen message for a given thread + * + * @return {integer|null} last seen message ID (if any) + */ + getLastSeenMessageID: function () { + return this._lastSeenMessageID || null; + }, + /** + * @override + * @return {mail.model.Message[]} */ - hasMessages: function () { - return !!(_.last(this._cache['[]'].messages)); + getMessages: function () { + return this._cache['[]'].messages; }, /** * Invalidate the caches of the thread |
