summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2018-03-15 11:18:57 +0100
committerAaron Bohy <aab@odoo.com>2018-03-16 08:08:38 +0100
commit75802f9afce0d2bc8825608732d04804b8e7f4e6 (patch)
treeb49c24a303c514952093dffa05892a69cb8e8aa2 /addons/web/static/src/js
parentb574104ebc9c436f93fa7444469f753562108df0 (diff)
[FIX] web: ActionManager: concurrent window actions
This rev. strengthens the handling of concurrent actions of type 'ir.actions.act_window' in the ActionManager. In particular, the two following cases are now handled: - execute an action A, its 'load_views' RPC takes a while, during that time, execute an action B: A can be dropped, meaning that it doesn't need to fetch its data, and thus it should not be appended to the DOM (nor appear in the breadcrumbs) ; - execute an action A, its 'read' or 'search_read' RPC takes a while, during that time, execute an action B: A can be dropped and should not be appended to the DOM (nor appear in the breadcrumbs).
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/chrome/action_manager.js17
-rw-r--r--addons/web/static/src/js/chrome/action_manager_act_window.js48
2 files changed, 37 insertions, 28 deletions
diff --git a/addons/web/static/src/js/chrome/action_manager.js b/addons/web/static/src/js/chrome/action_manager.js
index 19750915b0b..b8d66bed42d 100644
--- a/addons/web/static/src/js/chrome/action_manager.js
+++ b/addons/web/static/src/js/chrome/action_manager.js
@@ -61,7 +61,6 @@ var ActionManager = Widget.extend({
// dialog (i.e. coming from an action with target='new')
this.currentDialogController = null;
},
-
/**
* @override
*/
@@ -144,7 +143,7 @@ var ActionManager = Widget.extend({
* 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;
options = _.defaults({}, options, {
@@ -907,13 +906,13 @@ var ActionManager = Widget.extend({
}
},
/**
- * Intercepts and triggers a redirection on a link
- *
- * @private
- * @param {OdooEvent} ev
- * @param {integer} ev.data.res_id
- * @param {string} ev.data.res_model
- */
+ * Intercepts and triggers a redirection on a link.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ * @param {integer} ev.data.res_id
+ * @param {string} ev.data.res_model
+ */
_onRedirect: function (ev) {
this.do_action({
type:'ir.actions.act_window',
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 dfb512900e8..4e636de6355 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
@@ -224,6 +224,31 @@ ActionManager.include({
return action.controllers[viewType];
},
/**
+ * Destroys the controllers and search view of a given action of type
+ * 'ir.actions.act_window'.
+ *
+ * @private
+ * @param {Object} action
+ */
+ _destroyWindowAction: function (action) {
+ var self = this;
+ _.each(action.controllers, function (controllerDef) {
+ controllerDef.then(function (controller) {
+ delete self.controllers[controller.jsID];
+ if (controller.widget) {
+ controller.widget.destroy();
+ }
+ });
+ // reject the deferred if it is not yet resolved, so that the
+ // controller is correctly destroyed as soon as it is ready, and
+ // its reference is removed
+ controllerDef.reject();
+ });
+ if (action.searchView) {
+ action.searchView.destroy();
+ }
+ },
+ /**
* Executes actions of type 'ir.actions.act_window'.
*
* @private
@@ -245,7 +270,7 @@ ActionManager.include({
}
action.flags = this._generateActionFlags(action);
- return this._loadViews(action).then(function (fieldsViews) {
+ return this.dp.add(this._loadViews(action)).then(function (fieldsViews) {
var views = self._generateActionViews(action, fieldsViews);
action._views = action.views; // save the initial attribute
action.views = views;
@@ -291,7 +316,7 @@ ActionManager.include({
if (mainView) {
defs.push(self._createViewController(action, mainView.type, {}, {lazy: true}));
}
- return $.when.apply($, defs);
+ return self.dp.add($.when.apply($, defs));
}).then(function (controller, lazyLoadedController) {
action.controllerID = controller.jsID;
return self._executeAction(action, options).done(function () {
@@ -302,7 +327,7 @@ ActionManager.include({
}, {clear: false});
}
});
- });
+ }).fail(self._destroyWindowAction.bind(self, action));
});
},
/**
@@ -490,25 +515,10 @@ ActionManager.include({
* @private
*/
_removeAction: function (actionID) {
- var self = this;
var action = this.actions[actionID];
if (action.type === 'ir.actions.act_window') {
delete this.actions[action.jsID];
- _.each(action.controllers, function (controllerDef) {
- controllerDef.then(function (controller) {
- delete self.controllers[controller.jsID];
- if (controller.widget) {
- controller.widget.destroy();
- }
- });
- // reject the deferred if it is not yet resolved, so that the
- // controller is correctly destroyed as soon as it is ready, and
- // its reference is removed
- controllerDef.reject();
- });
- if (action.searchView) {
- action.searchView.destroy();
- }
+ this._destroyWindowAction(action);
} else {
this._super.apply(this, arguments);
}