diff options
Diffstat (limited to 'addons/mail/static/src/components/messaging_menu/messaging_menu.js')
| -rw-r--r-- | addons/mail/static/src/components/messaging_menu/messaging_menu.js | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/addons/mail/static/src/components/messaging_menu/messaging_menu.js b/addons/mail/static/src/components/messaging_menu/messaging_menu.js new file mode 100644 index 00000000..9eb7fd71 --- /dev/null +++ b/addons/mail/static/src/components/messaging_menu/messaging_menu.js @@ -0,0 +1,234 @@ +odoo.define('mail/static/src/components/messaging_menu/messaging_menu.js', function (require) { +'use strict'; + +const components = { + AutocompleteInput: require('mail/static/src/components/autocomplete_input/autocomplete_input.js'), + MobileMessagingNavbar: require('mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.js'), + NotificationList: require('mail/static/src/components/notification_list/notification_list.js'), +}; +const useShouldUpdateBasedOnProps = require('mail/static/src/component_hooks/use_should_update_based_on_props/use_should_update_based_on_props.js'); +const useStore = require('mail/static/src/component_hooks/use_store/use_store.js'); + +const patchMixin = require('web.patchMixin'); + +const { Component } = owl; + +class MessagingMenu extends Component { + + /** + * @override + */ + constructor(...args) { + super(...args); + /** + * global JS generated ID for this component. Useful to provide a + * custom class to autocomplete input, so that click in an autocomplete + * item is not considered as a click away from messaging menu in mobile. + */ + this.id = _.uniqueId('o_messagingMenu_'); + useShouldUpdateBasedOnProps(); + useStore(props => { + return { + isDeviceMobile: this.env.messaging && this.env.messaging.device.isMobile, + isDiscussOpen: this.env.messaging && this.env.messaging.discuss.isOpen, + isMessagingInitialized: this.env.isMessagingInitialized(), + messagingMenu: this.env.messaging && this.env.messaging.messagingMenu.__state, + }; + }); + + // bind since passed as props + this._onMobileNewMessageInputSelect = this._onMobileNewMessageInputSelect.bind(this); + this._onMobileNewMessageInputSource = this._onMobileNewMessageInputSource.bind(this); + this._onClickCaptureGlobal = this._onClickCaptureGlobal.bind(this); + this._constructor(...args); + } + + /** + * Allows patching constructor. + */ + _constructor() {} + + mounted() { + document.addEventListener('click', this._onClickCaptureGlobal, true); + } + + willUnmount() { + document.removeEventListener('click', this._onClickCaptureGlobal, true); + } + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * @returns {mail.discuss} + */ + get discuss() { + return this.env.messaging && this.env.messaging.discuss; + } + + /** + * @returns {mail.messaging_menu} + */ + get messagingMenu() { + return this.env.messaging && this.env.messaging.messagingMenu; + } + + /** + * @returns {string} + */ + get mobileNewMessageInputPlaceholder() { + return this.env._t("Search user..."); + } + + /** + * @returns {Object[]} + */ + get tabs() { + return [{ + icon: 'fa fa-envelope', + id: 'all', + label: this.env._t("All"), + }, { + icon: 'fa fa-user', + id: 'chat', + label: this.env._t("Chat"), + }, { + icon: 'fa fa-users', + id: 'channel', + label: this.env._t("Channel"), + }]; + } + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Closes the menu when clicking outside, if appropriate. + * + * @private + * @param {MouseEvent} ev + */ + _onClickCaptureGlobal(ev) { + if (!this.env.messaging) { + /** + * Messaging not created, which means essential models like + * messaging menu are not ready, so user interactions are omitted + * during this (short) period of time. + */ + return; + } + // ignore click inside the menu + if (this.el.contains(ev.target)) { + return; + } + // in all other cases: close the messaging menu when clicking outside + this.messagingMenu.close(); + } + + /** + * @private + * @param {MouseEvent} ev + */ + _onClickDesktopTabButton(ev) { + this.messagingMenu.update({ activeTabId: ev.currentTarget.dataset.tabId }); + } + + /** + * @private + * @param {MouseEvent} ev + */ + _onClickNewMessage(ev) { + if (!this.env.messaging.device.isMobile) { + this.env.messaging.chatWindowManager.openNewMessage(); + this.messagingMenu.close(); + } else { + this.messagingMenu.toggleMobileNewMessage(); + } + } + + /** + * @private + * @param {MouseEvent} ev + */ + _onClickToggler(ev) { + // avoid following dummy href + ev.preventDefault(); + if (!this.env.messaging) { + /** + * Messaging not created, which means essential models like + * messaging menu are not ready, so user interactions are omitted + * during this (short) period of time. + */ + return; + } + this.messagingMenu.toggleOpen(); + } + + /** + * @private + * @param {CustomEvent} ev + */ + _onHideMobileNewMessage(ev) { + ev.stopPropagation(); + this.messagingMenu.toggleMobileNewMessage(); + } + + /** + * @private + * @param {Event} ev + * @param {Object} ui + * @param {Object} ui.item + * @param {integer} ui.item.id + */ + _onMobileNewMessageInputSelect(ev, ui) { + this.env.messaging.openChat({ partnerId: ui.item.id }); + } + + /** + * @private + * @param {Object} req + * @param {string} req.term + * @param {function} res + */ + _onMobileNewMessageInputSource(req, res) { + const value = _.escape(req.term); + this.env.models['mail.partner'].imSearch({ + callback: partners => { + const suggestions = partners.map(partner => { + return { + id: partner.id, + value: partner.nameOrDisplayName, + label: partner.nameOrDisplayName, + }; + }); + res(_.sortBy(suggestions, 'label')); + }, + keyword: value, + limit: 10, + }); + } + + /** + * @private + * @param {CustomEvent} ev + * @param {Object} ev.detail + * @param {string} ev.detail.tabId + */ + _onSelectMobileNavbarTab(ev) { + ev.stopPropagation(); + this.messagingMenu.update({ activeTabId: ev.detail.tabId }); + } + +} + +Object.assign(MessagingMenu, { + components, + props: {}, + template: 'mail.MessagingMenu', +}); + +return patchMixin(MessagingMenu); + +}); |
