diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-03-09 16:25:58 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-03-09 16:25:58 +0100 |
| commit | 0f57bdba72b592ca097d4cd3da99a75883d8c623 (patch) | |
| tree | 94eef0c9aaf885c7f717bab5e468ca72b59a219d /addons/web/static/src/js/chrome | |
| parent | 35f0797002e44ce5673e9fab63710d2764329694 (diff) | |
| parent | 42659dc70c2b9b124e7e4fdc0449f660c3de5c76 (diff) | |
[MERGE] forward port branch saas-11.2 up to 42659dc70c2
Diffstat (limited to 'addons/web/static/src/js/chrome')
5 files changed, 102 insertions, 15 deletions
diff --git a/addons/web/static/src/js/chrome/abstract_web_client.js b/addons/web/static/src/js/chrome/abstract_web_client.js index b4b192c1ea9..9fe38adbde6 100644 --- a/addons/web/static/src/js/chrome/abstract_web_client.js +++ b/addons/web/static/src/js/chrome/abstract_web_client.js @@ -68,6 +68,7 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, { .load_filters(event.data.dataset, event.data.action_id) .then(event.data.on_success); }, + create_filter: '_onCreateFilter', push_state: '_onPushState', show_effect: '_onShowEffect', // session @@ -338,6 +339,18 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, { //-------------------------------------------------------------------------- /** + * @private + * @param {OdooEvent} e + * @param {Object} e.data.filter the filter description + * @param {function} e.data.on_success called when the RPC succeeds with its + * returned value as argument + */ + _onCreateFilter: function (e) { + data_manager + .create_filter(e.data.filter) + .then(e.data.on_success); + }, + /** * Displays a warning in a dialog of with the NotificationManager * * @private diff --git a/addons/web/static/src/js/chrome/action_manager.js b/addons/web/static/src/js/chrome/action_manager.js index e213b55189d..1e9c52238bc 100644 --- a/addons/web/static/src/js/chrome/action_manager.js +++ b/addons/web/static/src/js/chrome/action_manager.js @@ -136,9 +136,10 @@ var ActionManager = Widget.extend({ * is useful when we come from a loadState()) * @param {boolean} [options.replace_last_action=false] set to true to * replace last part of the breadcrumbs with the action - * @return {Deferred} resolved when the action is loaded and appended to the - * DOM ; rejected if the action can't be executed (e.g. if doAction has - * been called to execute another action before this one was complete). + * @return {$.Deferred<Object>} resolved with the action when the action is + * loaded and appended to the DOM ; rejected if the action can't be + * executed (e.g. if doAction has been called to execute another action + * before this one was complete). */ doAction: function (action, options) { var self = this; @@ -175,7 +176,9 @@ var ActionManager = Widget.extend({ self._preprocessAction(action, options); - return self._handleAction(action, options); + return self._handleAction(action, options).then(function () { + return action; + }); }); }, /** @@ -349,6 +352,11 @@ var ActionManager = Widget.extend({ // toggle the fullscreen mode for actions in target='fullscreen' self._toggleFullscreen(); + // now that the action has been executed, force its 'pushState' + // flag to 'true', as we don't want to prevent its controller + // from pushing its state if it changes in the future + action.pushState = true; + return action; }) .fail(function () { diff --git a/addons/web/static/src/js/chrome/action_manager_act_window.js b/addons/web/static/src/js/chrome/action_manager_act_window.js index 9cfa99a9e7d..dfb512900e8 100644 --- a/addons/web/static/src/js/chrome/action_manager_act_window.js +++ b/addons/web/static/src/js/chrome/action_manager_act_window.js @@ -21,6 +21,7 @@ ActionManager.include({ custom_events: _.extend({}, ActionManager.prototype.custom_events, { env_updated: '_onEnvUpdated', execute_action: '_onExecuteAction', + get_controller_context: '_onGetControllerContext', search: '_onSearch', switch_view: '_onSwitchView', }), @@ -254,18 +255,26 @@ ActionManager.include({ action.env = self._generateActionEnv(action, options); action.controllers = {}; - // select the first view to display - var lazyLoadFirstView = false; + // select the first view to display, and optionally the main view + // which will be lazyloaded var firstView = options.viewType && _.findWhere(views, {type: options.viewType}); + var mainView; if (firstView) { if (!firstView.multiRecord && views[0].multiRecord) { - lazyLoadFirstView = true; + mainView = views[0]; } } else { firstView = views[0]; } - if (config.device.isMobile && !firstView.isMobileFriendly) { - firstView = _.findWhere(action.views, {isMobileFriendly: true}) || firstView; + + // use mobile-friendly view by default in mobile, if possible + if (config.device.isMobile) { + if (!firstView.isMobileFriendly) { + firstView = self._findMobileView(views, firstView.multiRecord) || firstView; + } + if (mainView && !mainView.isMobileFriendly) { + mainView = self._findMobileView(views, mainView.multiRecord) || mainView; + } } var def; @@ -279,8 +288,8 @@ ActionManager.include({ return $.when(def).then(function () { var defs = []; defs.push(self._createViewController(action, firstView.type)); - if (lazyLoadFirstView) { - defs.push(self._createViewController(action, views[0].type, {}, {lazy: true})); + if (mainView) { + defs.push(self._createViewController(action, mainView.type, {}, {lazy: true})); } return $.when.apply($, defs); }).then(function (controller, lazyLoadedController) { @@ -297,6 +306,22 @@ ActionManager.include({ }); }, /** + * Helper function to find the first mobile-friendly view, if any. + * + * @private + * @param {Array} views an array of views + * @param {boolean} multiRecord set to true iff we search for a multiRecord + * view + * @returns {Object|undefined} a mobile-friendly view of the requested + * multiRecord type, undefined if there is no such view + */ + _findMobileView: function (views, multiRecord) { + return _.findWhere(views, { + isMobileFriendly: true, + multiRecord: multiRecord, + }); + }, + /** * Generates the initial environment of a given action, which is a dict * containing information like the model name, the domain, the context... * That information is shared between the controllers of the corresponding @@ -716,6 +741,20 @@ ActionManager.include({ }); }, /** + * Handles a context request: provides to the caller the context of the + * current controller. + * + * @private + * @param {OdooEvent} ev + * @param {function} ev.data.callback used to send the requested context + */ + _onGetControllerContext: function (ev) { + ev.stopPropagation(); + var currentController = this.getCurrentController(); + var context = currentController && currentController.widget.getContext(); + ev.data.callback(context || {}); + }, + /** * Called when there is a change in the search view, so the current action's * environment needs to be updated with the new domain, context and groupby. * diff --git a/addons/web/static/src/js/chrome/control_panel.js b/addons/web/static/src/js/chrome/control_panel.js index 16b22761581..03b9e756bb7 100644 --- a/addons/web/static/src/js/chrome/control_panel.js +++ b/addons/web/static/src/js/chrome/control_panel.js @@ -154,7 +154,9 @@ var ControlPanel = Widget.extend({ this._attach_content(new_cp_content); // Update the searchview and switch buttons - this._update_search_view(status.searchview, status.search_view_hidden, status.groupable); + if (status.searchview || options.clear) { + this._update_search_view(status.searchview, status.search_view_hidden, status.groupable); + } if (status.active_view_selector) { this._update_switch_buttons(status.active_view_selector); } diff --git a/addons/web/static/src/js/chrome/search_menus.js b/addons/web/static/src/js/chrome/search_menus.js index 38f2bb7374c..d33cdce6500 100644 --- a/addons/web/static/src/js/chrome/search_menus.js +++ b/addons/web/static/src/js/chrome/search_menus.js @@ -97,10 +97,15 @@ return Widget.extend({ } var user_context = this.getSession().user_context; var search = this.searchview.build_search_data(); - var view_context = this.action.env.context; + var controllerContext; + this.trigger_up('get_controller_context', { + callback: function (ctx) { + controllerContext = ctx; + }, + }); var results = pyeval.eval_domains_and_contexts({ domains: search.domains, - contexts: [user_context].concat(search.contexts.concat(view_context || [])), + contexts: [user_context].concat(search.contexts.concat(controllerContext || [])), group_by_seq: search.groupbys || [], }); if (!_.isEmpty(results.group_by)) { @@ -123,7 +128,7 @@ return Widget.extend({ is_default: default_filter, action_id: this.action_id, }; - return data_manager.create_filter(filter).done(function (id) { + return this._createFilter(filter).then(function (id) { filter.id = id; self.toggle_save_menu(false); self.$save_name.find('input').val('').prop('checked', false); @@ -273,6 +278,26 @@ return Widget.extend({ } }); }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Creates a new search view filter. + * + * @private + * @param {Object} filter the filter description + * @returns {$.Deferred} resolved with the RPC's result when it succeeds + */ + _createFilter: function (filter) { + var def = $.Deferred(); + this.trigger_up('create_filter', { + filter: filter, + on_success: def.resolve.bind(def), + }); + return def; + }, }); }); |
