summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/components/messaging_menu/messaging_menu.js
diff options
context:
space:
mode:
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.js234
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);
+
+});