diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/chrome/web_client.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/chrome/web_client.js')
| -rw-r--r-- | addons/web/static/src/js/chrome/web_client.js | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js new file mode 100644 index 00000000..3522a7fc --- /dev/null +++ b/addons/web/static/src/js/chrome/web_client.js @@ -0,0 +1,238 @@ +odoo.define('web.WebClient', function (require) { +"use strict"; + +var AbstractWebClient = require('web.AbstractWebClient'); +var config = require('web.config'); +var core = require('web.core'); +var data_manager = require('web.data_manager'); +var dom = require('web.dom'); +var Menu = require('web.Menu'); +var session = require('web.session'); + +return AbstractWebClient.extend({ + custom_events: _.extend({}, AbstractWebClient.prototype.custom_events, { + app_clicked: 'on_app_clicked', + menu_clicked: 'on_menu_clicked', + }), + start: function () { + core.bus.on('change_menu_section', this, function (menuID) { + this.do_push_state(_.extend($.bbq.getState(), { + menu_id: menuID, + })); + }); + + return this._super.apply(this, arguments); + }, + bind_events: function () { + var self = this; + this._super.apply(this, arguments); + + /* + Small patch to allow having a link with a href towards an anchor. Since odoo use hashtag + to represent the current state of the view, we can't easily distinguish between a link + towards an anchor and a link towards anoter view/state. If we want to navigate towards an + anchor, we must not change the hash of the url otherwise we will be redirected to the app + switcher instead. + To check if we have an anchor, first check if we have an href attributes starting with #. + Try to find a element in the DOM using JQuery selector. + If we have a match, it means that it is probably a link to an anchor, so we jump to that anchor. + */ + this.$el.on('click', 'a', function (ev) { + var disable_anchor = ev.target.attributes.disable_anchor; + if (disable_anchor && disable_anchor.value === "true") { + return; + } + + var href = ev.target.attributes.href; + if (href) { + if (href.value[0] === '#' && href.value.length > 1) { + if (self.$("[id='"+href.value.substr(1)+"']").length) { + ev.preventDefault(); + self.trigger_up('scrollTo', {'selector': href.value}); + } + } + } + }); + }, + load_menus: function () { + return (odoo.loadMenusPromise || odoo.reloadMenus()) + .then(function (menuData) { + // Compute action_id if not defined on a top menu item + for (var i = 0; i < menuData.children.length; i++) { + var child = menuData.children[i]; + if (child.action === false) { + while (child.children && child.children.length) { + child = child.children[0]; + if (child.action) { + menuData.children[i].action = child.action; + break; + } + } + } + } + odoo.loadMenusPromise = null; + return menuData; + }); + }, + async show_application() { + this.set_title(); + + await this.menu_dp.add(this.instanciate_menu_widgets()); + $(window).bind('hashchange', this.on_hashchange); + + const state = $.bbq.getState(true); + if (!_.isEqual(_.keys(state), ["cids"])) { + return this.on_hashchange(); + } + + const [data] = await this.menu_dp.add(this._rpc({ + model: 'res.users', + method: 'read', + args: [session.uid, ["action_id"]], + })); + if (data.action_id) { + await this.do_action(data.action_id[0]); + this.menu.change_menu_section(this.menu.action_id_to_primary_menu_id(data.action_id[0])); + return; + } + + if (!this.menu.openFirstApp()) { + this.trigger_up('webclient_started'); + } + }, + + instanciate_menu_widgets: function () { + var self = this; + var proms = []; + return this.load_menus().then(function (menuData) { + self.menu_data = menuData; + + // Here, we instanciate every menu widgets and we immediately append them into dummy + // document fragments, so that their `start` method are executed before inserting them + // into the DOM. + if (self.menu) { + self.menu.destroy(); + } + self.menu = new Menu(self, menuData); + proms.push(self.menu.prependTo(self.$el)); + return Promise.all(proms); + }); + }, + + // -------------------------------------------------------------- + // URL state handling + // -------------------------------------------------------------- + on_hashchange: function (event) { + if (this._ignore_hashchange) { + this._ignore_hashchange = false; + return Promise.resolve(); + } + + var self = this; + return this.clear_uncommitted_changes().then(function () { + var stringstate = $.bbq.getState(false); + if (!_.isEqual(self._current_state, stringstate)) { + var state = $.bbq.getState(true); + if (state.action || (state.model && (state.view_type || state.id))) { + return self.menu_dp.add(self.action_manager.loadState(state, !!self._current_state)).then(function () { + if (state.menu_id) { + if (state.menu_id !== self.menu.current_primary_menu) { + core.bus.trigger('change_menu_section', state.menu_id); + } + } else { + var action = self.action_manager.getCurrentAction(); + if (action) { + var menu_id = self.menu.action_id_to_primary_menu_id(action.id); + core.bus.trigger('change_menu_section', menu_id); + } + } + }); + } else if (state.menu_id) { + var action_id = self.menu.menu_id_to_action_id(state.menu_id); + return self.menu_dp.add(self.do_action(action_id, {clear_breadcrumbs: true})).then(function () { + core.bus.trigger('change_menu_section', state.menu_id); + }); + } else { + self.menu.openFirstApp(); + } + } + self._current_state = stringstate; + }, function () { + if (event) { + self._ignore_hashchange = true; + window.location = event.originalEvent.oldURL; + } + }); + }, + + // -------------------------------------------------------------- + // Menu handling + // -------------------------------------------------------------- + on_app_clicked: function (ev) { + var self = this; + return this.menu_dp.add(data_manager.load_action(ev.data.action_id)) + .then(function (result) { + return self.action_mutex.exec(function () { + var completed = new Promise(function (resolve, reject) { + var options = _.extend({}, ev.data.options, { + clear_breadcrumbs: true, + action_menu_id: ev.data.menu_id, + }); + + Promise.resolve(self._openMenu(result, options)) + .then(function() { + self._on_app_clicked_done(ev) + .then(resolve) + .guardedCatch(reject); + }).guardedCatch(function() { + resolve(); + }); + setTimeout(function () { + resolve(); + }, 2000); + }); + return completed; + }); + }); + }, + _on_app_clicked_done: function (ev) { + core.bus.trigger('change_menu_section', ev.data.menu_id); + return Promise.resolve(); + }, + on_menu_clicked: function (ev) { + var self = this; + return this.menu_dp.add(data_manager.load_action(ev.data.action_id)) + .then(function (result) { + self.$el.removeClass('o_mobile_menu_opened'); + + return self.action_mutex.exec(function () { + var completed = new Promise(function (resolve, reject) { + Promise.resolve(self._openMenu(result, { + clear_breadcrumbs: true, + })).then(resolve).guardedCatch(reject); + + setTimeout(function () { + resolve(); + }, 2000); + }); + return completed; + }); + }).guardedCatch(function () { + self.$el.removeClass('o_mobile_menu_opened'); + }); + }, + /** + * Open the action linked to a menu. + * This function is mostly used to allow override in other modules. + * + * @private + * @param {Object} action + * @param {Object} options + * @returns {Promise} + */ + _openMenu: function (action, options) { + return this.do_action(action, options); + }, +}); + +}); |
