diff options
| author | Alexandre Kühn <aku@odoo.com> | 2018-08-11 20:30:51 +0200 |
|---|---|---|
| committer | Alexandre Kühn <aku@odoo.com> | 2018-08-13 14:17:27 +0200 |
| commit | f2302dfb27dd7f6a0dee7c65ab75b62a01706264 (patch) | |
| tree | d58fef9e2e8a5b98c0680f28fc92e24992236029 /addons/mail/static/src/js/models/threads/searchable_thread.js | |
| parent | 3de97f168956a7c22c3af6b72950cf28554f4139 (diff) | |
[REF][FIX] mail, im_livechat: various improvements (JS)
This commit makes a lot of small improvements of the JS of mail and
related modules.
A. Mail Manager
---------------
im_support:
- [REF] Slightly more robust way to determine a support
message, so that it more reliably falls back on
default kind of message (i.e. support channel UUID
should be clearly set).
mail:
- [REF] Improved method names for readability purposes.
Some examples:
- `fetchFromServer` becomes `fetchMailStateFromServer`
- `_initialize{*}` becomes `_update{*}FromServer`
- `_isModerator` becomes `_isMyselfModerator`
- [REF] Use 'template' pattern design to make Include on
Mail Manager much more robust. In particular,
the flow is always as follow:
1. Initialize internal state.
2. Listen on buses.
3. Fetch mail data from server.
- [REF] Improved workflow for thread window workflow
(Shorter & more readable).
B. Mail Tests
-------------
- [REF] Thread Window Tests crashes with clean message when
there are some thread windows open before running the
tests.
C. (Model) Message
------------------
- [REF] Improved method names for readability purposes
(e.g. `isAuthor` becomes `isMyselfAuthor`).
D. (Model) Thread
-----------------
- [REF] Improved `init` parameters on each kind of thread.
- [REF] 'Thread With Cache' has been renamed to 'Searchable
Thread': it embraces all kinds of threads that can
be used with the search view.
- [REF] 'DM' has been renamed to 'DM Chat' (for clarity).
- [IMP] New Livechat model in the backend.
- [REF] No more direct instances of the Channel class: public
and private channels are now 'Multi-User' channels,
while DM Chat and Livechat are 'Two-User' channels:
This change has been made so that instances of classes
always have direct classes as "leaf" in the Class
modeling. It eases making changes to a certain model
without being too constrained by another model.
- [REF] As a consequence of above changed, the method `isChat`
has been renamed to `isTwoUserThread`.
This is to avoid confusion with the terminology
'chat', which is more like a shortcut for 'quick real-
time conversation'. In other words, the property of
'chat' depends of the way to interact on a thread, not
of the intrinsic type of the thread.
Still, some parts have kept the terminology 'chat',
such as in the systray messagin menu.
- [IMP] Added `message_added` and `message_posted` hooks,
which may be useful to easily hook on those events.
E. Thread Widget
----------------
- [REF] Now uses a `mail.model.AbstractThread` for the
rendering of a thread, instead of a list of
`{mail.model.AbstractMessage}`.
- [FIX] Stick thread scroll height to bottom on new rendering,
if it was previously at the bottom of the thread.
- [REF] Option ORDER has its meaning changed: it now refers
to the chronological order of messages in the thread,
in which DESC means 'from top to bottom', while ASC
means 'from bottom to top'.
- [REF] Improved doc on templates, in particular with the
option `ORDER`.
F. Thread Window
----------------
- [REF] Moved more logic to thread windows, which were
previously in Mail Window Manager.
- [REF] Now hides the thread widget attribute. So instead of
`threadWindow.threadWidget.isAtBottom()`, it uses
`threadWindow.isAtBottom()`.
- [FIX] New received messages when not having focus on Odoo
tab should always make the corresponding thread
windows "passive" (i.e. windows that keep threads
unread until click on them).
- [FIX] Blank thread window (i.e. 'New message' TW) correctly
opens Discuss with 'Inbox' when clicking on 'Expand'
Button in the title
- [FIX] Do not display the composer for channels with property
'mass-mailing' set in thread windows.
G. (Website) Livechat
---------------------
- [REF] Some `trigger` have been turned into `trigger_up`.
- [REF] Some logic has been moved to models (e.g.
`{im_livechat.model.WebsiteLivechat}`), from
`{im_livechat.im_livechat.LivechatButton}`.
- [FIX] New messages should be received in real-time. The
longpolling was broken with a recent refactoring on
bus service (6448420c5dd160470e465dee7729d19d8d5e7bab).
Diffstat (limited to 'addons/mail/static/src/js/models/threads/searchable_thread.js')
| -rw-r--r-- | addons/mail/static/src/js/models/threads/searchable_thread.js | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/addons/mail/static/src/js/models/threads/searchable_thread.js b/addons/mail/static/src/js/models/threads/searchable_thread.js new file mode 100644 index 00000000000..fef42c3ffc4 --- /dev/null +++ b/addons/mail/static/src/js/models/threads/searchable_thread.js @@ -0,0 +1,208 @@ +odoo.define('mail.model.SearchableThread', function (require) { +"use strict"; + +var Thread = require('mail.model.Thread'); + +var session = require('web.session'); + +/** + * This is a version of a thread that is handling a cache. + * Basically, this cache is an object indexed by stringified indexes. + * These indexes represent the domain of messages that match this domain. + * + * Any threads that are instances of this Class can be used with a search view, + * in order to make searches on messages in a thread. + */ +var SearchableThread = Thread.extend({ + + /** + * @override + * @param {Object} params + * @param {Object} params.data + * @param {integer} [params.data.seen_message_id=undefined] + */ + init: function (params) { + this._super.apply(this, arguments); + + this._cache = { + '[]': { + allHistoryLoaded: false, + loaded: false, + messages: [], + } + }; + this._lastSeenMessageID = params.data.seen_message_id; + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * @override + * @param {Array} [domain] + * @param {boolean} [loadMore=false] + */ + fetchMessages: function (domain, loadMore) { + if (loadMore) { + return this._fetchMessages(domain, true); + } + var cache = this._getCache(domain); + if (cache.loaded) { + return $.when(cache.messages); + } else { + return this._fetchMessages(domain); + } + }, + /** + * 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[]} + */ + getMessages: function () { + return this._cache['[]'].messages; + }, + /** + * Invalidate the caches of the thread + */ + invalidateCaches: function () { + this._cache = _.pick(this._cache, '[]'); + }, + /** + * State whether all messages have been loaded or not + * + * @param {Array} domain + * @return {boolean} + */ + isAllHistoryLoaded: function (domain) { + return this._getCache(domain).allHistoryLoaded; + }, + /** + * Remove message with ID `messageID` from this thread + * + * This is equivalent to removing this message from all the caches + * + * @param {integer} messageID + */ + removeMessage: function (messageID) { + _.each(this._cache, function (cache) { + cache.messages = _.reject(cache.messages, function (message) { + return message.getID() === messageID; + }); + }); + }, + /** + * Set 'messageID' as the ID of the last message seen in this thread + * + * @param {integer} messageID + */ + setLastSeenMessageID: function (messageID) { + this._lastSeenMessageID = messageID; + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Add the message to this thread + * + * @override + * @private + * @param {mail.model.Message} message + * @param {Array} domain + */ + _addMessage: function (message, domain) { + this._super.apply(this, arguments); + var cache = this._getCache(domain); + var index = _.sortedIndex(cache.messages, message, function (msg) { + return msg.getID(); + }); + if (cache.messages[index] !== message) { + cache.messages.splice(index, 0, message); + } + }, + /** + * Gets messages from thread + * + * @override + * @private + * @param {Array} [pDomain] filter on the messages of the channel + * @param {boolean} [loadMore] Whether it should load more message + * @return {$.Promise<mail.model.Message[]>} resolved with list of messages + */ + _fetchMessages: function (pDomain, loadMore) { + var self = this; + + var domain = this._getThreadDomain(); + + var cache = this._getCache(pDomain); + if (pDomain) { + domain = domain.concat(pDomain || []); + } + if (loadMore) { + var minMessageID = cache.messages[0].getID(); + domain = [['id', '<', minMessageID]].concat(domain); + } + return this._rpc({ + model: 'mail.message', + method: 'message_fetch', + args: [domain], + kwargs: { + limit: this._FETCH_LIMIT, + context: session.user_context + }, + }).then(function (messages) { + if (!cache.allHistoryLoaded) { + cache.allHistoryLoaded = messages.length < self._FETCH_LIMIT; + } + cache.loaded = true; + _.each(messages, function (message) { + self.call('mail_service', 'addMessage', message, { + silent: true, + domain: pDomain, + }); + }); + cache = self._getCache(pDomain || []); + return cache.messages; + }); + }, + /** + * Get thread content from the cache + * Useful to get cached messages. + * + * @private + * @param {Array} domain + * @return {Object|undefined} + */ + _getCache: function (domain) { + var stringifiedDomain = JSON.stringify(domain || []); + if (!this._cache[stringifiedDomain]) { + this._cache[stringifiedDomain] = { + allHistoryLoaded: false, + loaded: false, + messages: [], + }; + } + return this._cache[stringifiedDomain]; + }, + /** + * Get the domain to fetch all the messages in the current thread + * + * @abstract + * @private + * @returns {Array} + */ + _getThreadDomain: function () {}, +}); + +return SearchableThread; + +}); |
