summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/chrome
diff options
context:
space:
mode:
authorVincent Schippefilt <vsc@odoo.com>2019-03-06 14:02:32 +0100
committerAaron Bohy <aab@odoo.com>2019-03-06 20:07:17 +0100
commitab56e637b7f97ddcdbcc9baea99ae097e342409c (patch)
tree4cb47da9f7ef89b19d18429220a7507470ec12a9 /addons/web/static/src/js/chrome
parenteeed894fd50e477135e1ac9a82f6e98ce063ab90 (diff)
[REF] web: adapt code after jQuery update
Part of task 1896658 Co-authored-by: Aaron Bohy <aab@odoo.com> Co-authored-by: Christophe Matthieu <chm@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com> Co-authored-by: David Monjoie <dmo@odoo.com> Co-authored-by: Martin Geubelle <mge@odoo.com> Co-authored-by: svs-odoo <svs@odoo.com> Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
Diffstat (limited to 'addons/web/static/src/js/chrome')
-rw-r--r--addons/web/static/src/js/chrome/abstract_action.js4
-rw-r--r--addons/web/static/src/js/chrome/abstract_web_client.js11
-rw-r--r--addons/web/static/src/js/chrome/action_manager.js73
-rw-r--r--addons/web/static/src/js/chrome/action_manager_act_window.js105
-rw-r--r--addons/web/static/src/js/chrome/action_manager_report.js57
-rw-r--r--addons/web/static/src/js/chrome/action_mixin.js8
-rw-r--r--addons/web/static/src/js/chrome/loading.js2
-rw-r--r--addons/web/static/src/js/chrome/menu.js12
-rw-r--r--addons/web/static/src/js/chrome/pager.js7
-rw-r--r--addons/web/static/src/js/chrome/sidebar.js2
-rw-r--r--addons/web/static/src/js/chrome/systray_menu.js9
-rw-r--r--addons/web/static/src/js/chrome/user_menu.js8
-rw-r--r--addons/web/static/src/js/chrome/web_client.js65
13 files changed, 193 insertions, 170 deletions
diff --git a/addons/web/static/src/js/chrome/abstract_action.js b/addons/web/static/src/js/chrome/abstract_action.js
index a5f98434ddb..1b258ccc6f6 100644
--- a/addons/web/static/src/js/chrome/abstract_action.js
+++ b/addons/web/static/src/js/chrome/abstract_action.js
@@ -104,7 +104,7 @@ var AbstractAction = Widget.extend(ActionMixin, {
};
});
}
- return $.when(def).then(function () {
+ return Promise.resolve(def).then(function () {
var controlPanelView = new self.config.ControlPanelView(params);
return controlPanelView.getController(self).then(function (controlPanel) {
self._controlPanel = controlPanel;
@@ -112,7 +112,7 @@ var AbstractAction = Widget.extend(ActionMixin, {
});
});
}
- return $.when();
+ return Promise.resolve();
},
/**
* @override
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 7082f26e69d..68ac157868d 100644
--- a/addons/web/static/src/js/chrome/abstract_web_client.js
+++ b/addons/web/static/src/js/chrome/abstract_web_client.js
@@ -78,7 +78,7 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
if (event.data.on_success) {
event.data.on_success(result);
}
- }).fail(function (result) {
+ }).guardedCatch(function (result) {
if (event.data.on_fail) {
event.data.on_fail(result);
}
@@ -116,17 +116,17 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
.then(function () {
self.$el.toggleClass('o_rtl', _t.database.parameters.direction === "rtl");
self.bind_events();
- return $.when(
+ return Promise.all([
self.set_action_manager(),
self.set_loading()
- );
+ ]);
}).then(function () {
if (session.session_is_valid()) {
return self.show_application();
} else {
// database manager needs the webclient to keep going even
// though it has no valid session
- return $.when();
+ return Promise.resolve();
}
}).then(function () {
// Listen to 'scroll' event and propagate it on main bus
@@ -145,12 +145,13 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function () {
$(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter');
});
+ // TODO: this handler seems useless since 11.0, should be removed
this.$el.on('click', '.oe_dropdown_toggle', function (ev) {
ev.preventDefault();
var $toggle = $(this);
var doc_width = $(document).width();
var $menu = $toggle.siblings('.oe_dropdown_menu');
- $menu = $menu.size() >= 1 ? $menu : $toggle.find('.oe_dropdown_menu');
+ $menu = $menu.length >= 1 ? $menu : $toggle.find('.oe_dropdown_menu');
var state = $menu.is('.oe_opened');
setTimeout(function () {
// Do not alter propagation
diff --git a/addons/web/static/src/js/chrome/action_manager.js b/addons/web/static/src/js/chrome/action_manager.js
index 107c6e314eb..0537b45deb5 100644
--- a/addons/web/static/src/js/chrome/action_manager.js
+++ b/addons/web/static/src/js/chrome/action_manager.js
@@ -92,7 +92,7 @@ var ActionManager = Widget.extend({
* will be restored. It ensures that the current controller can be left (for
* instance, that it has no unsaved changes).
*
- * @returns {Deferred} resolved if the current controller can be left,
+ * @returns {Promise} resolved if the current controller can be left,
* rejected otherwise.
*/
clearUncommittedChanges: function () {
@@ -100,7 +100,7 @@ var ActionManager = Widget.extend({
if (currentController) {
return currentController.widget.canBeRemoved();
}
- return $.when();
+ return Promise.resolve();
},
/**
* This is the entry point to execute Odoo actions, given as an ID in
@@ -123,7 +123,7 @@ 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<Object>} resolved with the action when the action is
+ * @return {Promise<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).
@@ -155,7 +155,7 @@ var ActionManager = Widget.extend({
});
}
- return this.dp.add($.when(def)).then(function () {
+ return this.dp.add(Promise.resolve(def)).then(function () {
// action.target 'main' is equivalent to 'current' except that it
// also clears the breadcrumbs
options.clear_breadcrumbs = action.target === 'main' ||
@@ -211,12 +211,12 @@ var ActionManager = Widget.extend({
* @param {Object} state
* @param {integer|string} [state.action] the action to execute (given its
* id or tag for client actions)
- * @returns {Deferred} resolved when the UI has been updated
+ * @returns {Promise} resolved when the UI has been updated
*/
loadState: function (state) {
var action;
if (!state.action) {
- return $.when();
+ return Promise.resolve();
}
if (_.isString(state.action) && core.action_registry.contains(state.action)) {
action = {
@@ -299,7 +299,7 @@ var ActionManager = Widget.extend({
* @param {string} [action.target="current"] set to "new" to render the
* controller in a dialog
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the controller is started and appended
+ * @returns {Promise} resolved when the controller is started and appended
*/
_executeAction: function (action, options) {
var self = this;
@@ -338,7 +338,7 @@ var ActionManager = Widget.extend({
return action;
})
- .fail(function () {
+ .guardedCatch(function () {
self._removeAction(action.jsID);
});
},
@@ -349,7 +349,7 @@ var ActionManager = Widget.extend({
* @private
* @param {Object} action
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the controller is rendered inside a
+ * @returns {Promise} resolved when the controller is rendered inside a
* dialog appended to the DOM
*/
_executeActionInDialog: function (action, options) {
@@ -401,7 +401,7 @@ var ActionManager = Widget.extend({
return action;
});
- }).fail(function () {
+ }).guardedCatch(function () {
self._removeAction(action.jsID);
});
},
@@ -412,14 +412,14 @@ var ActionManager = Widget.extend({
* @param {Object} action the description of the action to execute
* @param {string} action.tag the key of the action in the action_registry
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the client action has been executed
+ * @returns {Promise} resolved when the client action has been executed
*/
_executeClientAction: function (action, options) {
var self = this;
var ClientAction = core.action_registry.get(action.tag);
if (!ClientAction) {
console.error("Could not find client action " + action.tag, action);
- return $.Deferred().reject();
+ return Promise.reject();
}
if (!(ClientAction.prototype instanceof AbstractAction)) {
console.warn('The client action ' + action.tag + ' should be an instance of AbstractAction!');
@@ -431,7 +431,7 @@ var ActionManager = Widget.extend({
if (next) {
return this.doAction(next, options);
}
- return $.when();
+ return Promise.resolve();
}
var controllerID = _.uniqueId('controller_');
@@ -449,12 +449,14 @@ var ActionManager = Widget.extend({
};
this.controllers[controllerID] = controller;
action.controllerID = controllerID;
- return this._executeAction(action, options).done(function () {
+ var prom = this._executeAction(action, options);
+ prom.then(function () {
// AAB: this should be done automatically in AbstractAction, so that
// it can be overriden by actions that have specific stuff to push
// (e.g. Discuss, Views)
self._pushState(controllerID, {});
});
+ return prom;
},
/**
* Executes actions of type 'ir.actions.act_window_close', i.e. closes the
@@ -469,7 +471,7 @@ var ActionManager = Widget.extend({
* @param {Object} [action.effect] effect to show up, e.g. rainbow man.
* @param {Object} [action.infos] infos on performing the close action.
* Useful for providing some context for the `on_close` handler.
- * @returns {Deferred} resolved immediately
+ * @returns {Promise} resolved immediately
*/
_executeCloseAction: function (action, options) {
var result;
@@ -484,7 +486,7 @@ var ActionManager = Widget.extend({
this.trigger_up('show_effect', action.effect);
}
- return $.when(result);
+ return Promise.resolve(result);
},
/**
* Executes actions of type 'ir.actions.server'.
@@ -494,7 +496,7 @@ var ActionManager = Widget.extend({
* @param {integer} action.id the db ID of the action to execute
* @param {Object} [action.context]
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the action has been executed
+ * @returns {Promise} resolved when the action has been executed
*/
_executeServerAction: function (action, options) {
var self = this;
@@ -520,7 +522,7 @@ var ActionManager = Widget.extend({
* @param {string} [action.target] set to 'self' to redirect in the current page,
* redirects to a new page by default
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the redirection is done (immediately
+ * @returns {Promise} resolved when the redirection is done (immediately
* when redirecting to a new page)
*/
_executeURLAction: function (action, options) {
@@ -531,7 +533,7 @@ var ActionManager = Widget.extend({
if (action.target === 'self') {
framework.redirect(url);
- return $.Deferred();
+ return Promise.resolve();
} else {
var w = window.open(url, '_blank');
if (!w || w.closed || typeof w.closed === 'undefined') {
@@ -544,7 +546,7 @@ var ActionManager = Widget.extend({
options.on_close();
- return $.when();
+ return Promise.resolve();
},
/**
* Returns a description of the controllers in the given controller stack.
@@ -653,14 +655,14 @@ var ActionManager = Widget.extend({
* @param {Object} action
* @param {string} action.type
* @param {Object} options
- * @returns {Deferred} resolved when the action has been executed ; rejected
+ * @returns {Promise} resolved when the action has been executed ; rejected
* if the type of action isn't supported, or if the action can't be
* executed
*/
_handleAction: function (action, options) {
if (!action.type) {
console.error("No type for action", action);
- return $.Deferred().reject();
+ return Promise.reject();
}
switch (action.type) {
case 'ir.actions.act_url':
@@ -674,7 +676,7 @@ var ActionManager = Widget.extend({
default:
console.error("The ActionManager can't handle actions of type " +
action.type, action);
- return $.Deferred().reject();
+ return Promise.reject();
}
},
/**
@@ -749,16 +751,17 @@ var ActionManager = Widget.extend({
* @private
* @param {integer|string} action's ID or xml ID
* @param {Object} context
- * @returns {Deferred<Object>} resolved with the description of the action
+ * @returns {Promise<Object>} resolved with the description of the action
*/
_loadAction: function (actionID, context) {
- var def = $.Deferred();
- this.trigger_up('load_action', {
- actionID: actionID,
- context: context,
- on_success: def.resolve.bind(def),
+ var self = this;
+ return new Promise(function (resolve, reject) {
+ self.trigger_up('load_action', {
+ actionID: actionID,
+ context: context,
+ on_success: resolve,
+ });
});
- return def;
},
/**
* Preprocesses the action before it is handled by the ActionManager
@@ -815,20 +818,20 @@ var ActionManager = Widget.extend({
*
* @private
* @param {string} controllerID
- * @returns {Deferred} resolved when the controller has been restored
+ * @returns {Promise} resolved when the controller has been restored
*/
_restoreController: function (controllerID) {
var self = this;
var controller = this.controllers[controllerID];
// AAB: AbstractAction should define a proper hook to execute code when
- // it is restored (other than do_show), and it should return a deferred
+ // it is restored (other than do_show), and it should return a promise
var action = this.actions[controller.actionID];
var def;
if (action.on_reverse_breadcrumb) {
def = action.on_reverse_breadcrumb();
}
- return $.when(def).then(function () {
- return $.when(controller.widget.do_show()).then(function () {
+ return Promise.resolve(def).then(function () {
+ return Promise.resolve(controller.widget.do_show()).then(function () {
var index = _.indexOf(self.controllerStack, controllerID);
self._pushController(controller, index);
});
@@ -844,7 +847,7 @@ var ActionManager = Widget.extend({
*
* @private
* @param {Object} controller
- * @returns {Deferred<Object>} resolved with the controller when it is ready
+ * @returns {Promise<Object>} resolved with the controller when it is ready
*/
_startController: function (controller) {
var fragment = document.createDocumentFragment();
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 106f9f2aa47..d00b3a49eb2 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
@@ -144,7 +144,7 @@ ActionManager.include({
* @param {integer} [options.index=0] the controller's index in the stack
* @param {boolean} [options.lazy=false] set to true to differ the
* initialization of the controller's widget
- * @returns {Deferred<Object>} resolved with the created controller
+ * @returns {Promise<Object>} resolved with the created controller
*/
_createViewController: function (action, viewType, viewOptions, options) {
var self = this;
@@ -153,7 +153,7 @@ ActionManager.include({
// the requested view type isn't specified in the action (e.g.
// action with list view only, user clicks on a row in the list, it
// tries to switch to form view)
- return $.Deferred().reject();
+ return Promise.reject();
}
options = options || {};
@@ -186,26 +186,31 @@ ActionManager.include({
// communication with trigger_up
controllerID: controllerID,
});
+ var rejection;
var view = new viewDescr.Widget(viewDescr.fieldsView, viewOptions);
- var def = $.Deferred();
- action.controllers[viewType] = def;
- view.getController(this).then(function (widget) {
- if (def.state() === 'rejected') {
- // the deferred has been rejected meanwhile, meaning that
- // the action has been removed, so simply destroy the widget
- widget.destroy();
- } else {
- controller.widget = widget;
- def.resolve(controller);
- }
- }).fail(def.reject.bind(def));
- def.fail(function () {
+ var def = new Promise(function (resolve, reject) {
+ rejection = reject;
+ view.getController(self).then(function (widget) {
+ if (def.rejected) {
+ // the promise has been rejected meanwhile, meaning that
+ // the action has been removed, so simply destroy the widget
+ widget.destroy();
+ } else {
+ controller.widget = widget;
+ resolve(controller);
+ }
+ }).guardedCatch(reject);
+ });
+ // Need to define an reject property to call it into _destroyWindowAction
+ def.reject = rejection;
+ def.guardedCatch(function () {
+ def.rejected = true;
delete self.controllers[controllerID];
});
+ action.controllers[viewType] = def;
} else {
- action.controllers[viewType] = $.Deferred().resolve(controller);
+ action.controllers[viewType] = Promise.resolve(controller);
}
-
return action.controllers[viewType];
},
/**
@@ -217,18 +222,22 @@ ActionManager.include({
*/
_destroyWindowAction: function (action) {
var self = this;
- _.each(action.controllers, function (controllerDef) {
+ for (var c in action.controllers) {
+ var controllerDef = action.controllers[c];
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 controllerDef is not resolved yet, reject it so that the
+ // controller will be correctly destroyed as soon as it'll be ready,
+ // and its reference will be removed. Lazy-loaded controllers do
+ // not have a reject function on their promise
+ if (controllerDef.reject) {
+ controllerDef.reject();
+ }
+ }
},
/**
* Executes actions of type 'ir.actions.act_window'.
@@ -239,13 +248,13 @@ ActionManager.include({
* @param {Object} options @see doAction for details
* @param {integer} [options.resID] the current res ID
* @param {string} [options.viewType] the view to open
- * @returns {Deferred} resolved when the action is appended to the DOM
+ * @returns {Promise} resolved when the action is appended to the DOM
*/
_executeWindowAction: function (action, options) {
var self = this;
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 = action.views; // save the initial attribute
action.views = views;
action.controlPanelFieldsView = fieldsViews.search;
action.controllers = {};
@@ -285,7 +294,7 @@ ActionManager.include({
self.controllerStack.push(lazyLoadedController.jsID);
});
}
- return self.dp.add($.when(lazyViewDef))
+ return self.dp.add(Promise.resolve(lazyViewDef))
.then(function () {
var viewOptions = {
controllerState: options.controllerState,
@@ -300,7 +309,7 @@ ActionManager.include({
action.controllerID = controller.jsID;
return self._executeAction(action, options);
})
- .fail(self._destroyWindowAction.bind(self, action));
+ .guardedCatch(self._destroyWindowAction.bind(self, action));
});
},
/**
@@ -389,7 +398,7 @@ ActionManager.include({
*
* @private
* @param {Object} action
- * @returns {Deferred}
+ * @returns {Promise}
*/
_loadViews: function (action) {
var inDialog = action.target === 'new';
@@ -443,11 +452,11 @@ ActionManager.include({
return this.clearUncommittedChanges().then(function () {
// AAB: this will be done directly in AbstractAction's restore
// function
- var def;
+ var def = Promise.resolve();
if (action.on_reverse_breadcrumb) {
def = action.on_reverse_breadcrumb();
}
- return $.when(def).then(function () {
+ return Promise.resolve(def).then(function () {
return self._switchController(action, controller.viewType);
});
});
@@ -461,14 +470,14 @@ ActionManager.include({
* @private
* @param {Object} controller the controller to switch to
* @param {Object} [viewOptions]
- * @return {Deferred} resolved when the new controller is in the DOM
+ * @return {Promise} resolved when the new controller is in the DOM
*/
_switchController: function (action, viewType, viewOptions) {
var self = this;
var view = _.findWhere(action.views, {type: viewType});
if (!view) {
// can't switch to an unknown view
- return $.Deferred().reject();
+ return Promise.reject();
}
var currentController = this.getCurrentController();
var index;
@@ -519,28 +528,30 @@ ActionManager.include({
};
var controllerDef = action.controllers[viewType];
- if (!controllerDef || controllerDef.state() === 'rejected') {
- // if the controllerDef is rejected, it probably means that the js
- // code or the requests made to the server crashed. In that case,
- // if we reuse the same deferred, then the switch to the view is
- // definitely blocked. We want to use a new controller, even though
- // it is very likely that it will recrash again. At least, it will
- // give more feedback to the user, and it could happen that one
- // record crashes, but not another.
- controllerDef = newController();
- } else {
+ if (controllerDef) {
controllerDef = controllerDef.then(function (controller) {
if (!controller.widget) {
// lazy loaded -> load it now (with same jsID)
return newController(controller.jsID);
} else {
- return $.when(controller.widget.willRestore()).then(function () {
+ return Promise.resolve(controller.widget.willRestore()).then(function () {
return controller.widget.reload(viewOptions).then(function () {
return controller;
});
});
}
+ }, function () {
+ // if the controllerDef is rejected, it probably means that the js
+ // code or the requests made to the server crashed. In that case,
+ // if we reuse the same promise, then the switch to the view is
+ // definitely blocked. We want to use a new controller, even though
+ // it is very likely that it will recrash again. At least, it will
+ // give more feedback to the user, and it could happen that one
+ // record crashes, but not another.
+ return newController();
});
+ } else {
+ controllerDef = newController();
}
return this.dp.add(controllerDef).then(function (controller) {
@@ -577,11 +588,11 @@ ActionManager.include({
var env = ev.data.env;
var context = new Context(env.context, actionData.context || {});
var recordID = env.currentID || null; // pyUtils handles null value, not undefined
- var def = $.Deferred();
+ var def;
// determine the action to execute according to the actionData
if (actionData.special) {
- def = $.when({type: 'ir.actions.act_window_close', infos: 'special'});
+ def = Promise.resolve({type: 'ir.actions.act_window_close', infos: 'special'});
} else if (actionData.type === 'object') {
// call a Python Object method, which may return an action to execute
var args = recordID ? [[recordID]] : [env.resIDs];
@@ -611,13 +622,15 @@ ActionManager.include({
active_ids: env.resIDs,
active_id: recordID,
}));
+ } else {
+ def = new Promise(function () {});
}
// use the DropPrevious to prevent from executing the handler if another
// request (doAction, switchView...) has been done meanwhile ; execute
// the fail handler if the 'call_button' or 'loadAction' failed but not
// if the request failed due to the DropPrevious,
- def.fail(ev.data.on_fail);
+ def.guardedCatch(ev.data.on_fail);
this.dp.add(def).then(function (action) {
// show effect if button have effect attribute
// rainbowman can be displayed from two places: from attribute on a button or from python
diff --git a/addons/web/static/src/js/chrome/action_manager_report.js b/addons/web/static/src/js/chrome/action_manager_report.js
index 51922cd719f..30bac14006d 100644
--- a/addons/web/static/src/js/chrome/action_manager_report.js
+++ b/addons/web/static/src/js/chrome/action_manager_report.js
@@ -40,35 +40,36 @@ ActionManager.include({
* report generation and download.
*
* @param {string} url
- * @returns {Deferred} resolved when the report has been downloaded ;
+ * @returns {Promise} resolved when the report has been downloaded ;
* rejected if something went wrong during the report generation
*/
_downloadReport: function (url) {
+ var self = this;
framework.blockUI();
- var def = $.Deferred();
- var type = 'qweb-' + url.split('/')[2];
- var blocked = !session.get_file({
- url: '/report/download',
- data: {
- data: JSON.stringify([url, type]),
- },
- success: def.resolve.bind(def),
- error: function () {
- crash_manager.rpc_error.apply(crash_manager, arguments);
- def.reject();
- },
- complete: framework.unblockUI,
+ return new Promise(function (resolve, reject) {
+ var type = 'qweb-' + url.split('/')[2];
+ var blocked = !session.get_file({
+ url: '/report/download',
+ data: {
+ data: JSON.stringify([url, type]),
+ },
+ success: resolve,
+ error: function () {
+ crash_manager.rpc_error.apply(crash_manager, arguments);
+ reject();
+ },
+ complete: framework.unblockUI,
+ });
+ if (blocked) {
+ // AAB: this check should be done in get_file service directly,
+ // should not be the concern of the caller (and that way, get_file
+ // could return a promise)
+ var message = _t('A popup window with your report was blocked. You ' +
+ 'may need to change your browser settings to allow ' +
+ 'popup windows for this page.');
+ self.do_warn(_t('Warning'), message, true);
+ }
});
- if (blocked) {
- // AAB: this check should be done in get_file service directly,
- // should not be the concern of the caller (and that way, get_file
- // could return a deferred)
- var message = _t('A popup window with your report was blocked. You ' +
- 'may need to change your browser settings to allow ' +
- 'popup windows for this page.');
- this.do_warn(_t('Warning'), message, true);
- }
- return def;
},
/**
@@ -77,7 +78,7 @@ ActionManager.include({
* @private
* @param {Object} action the description of the action to execute
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the action has been executed
+ * @returns {Promise} resolved when the action has been executed
*/
_triggerDownload: function (action, options, type){
var self = this;
@@ -97,7 +98,7 @@ ActionManager.include({
* @private
* @param {Object} action the description of the action to execute
* @param {Object} options @see doAction for details
- * @returns {Deferred} resolved when the action has been executed
+ * @returns {Promise} resolved when the action has been executed
*/
_executeReportAction: function (action, options) {
var self = this;
@@ -125,7 +126,7 @@ ActionManager.include({
} else {
console.error("The ActionManager can't handle reports of type " +
action.report_type, action);
- return $.Deferred().reject();
+ return Promise.reject();
}
},
/**
@@ -135,7 +136,7 @@ ActionManager.include({
*
* @param {Object} action
* @param {Object} options
- * @returns {Deferred} resolved when the client action has been executed
+ * @returns {Promise} resolved when the client action has been executed
*/
_executeReportClientAction: function (action, options) {
var urls = this._makeReportUrls(action);
diff --git a/addons/web/static/src/js/chrome/action_mixin.js b/addons/web/static/src/js/chrome/action_mixin.js
index 92d6716a7c0..02345e7e969 100644
--- a/addons/web/static/src/js/chrome/action_mixin.js
+++ b/addons/web/static/src/js/chrome/action_mixin.js
@@ -75,7 +75,7 @@ var ActionMixin = {
* Called by the action manager when action is restored (typically, when the
* user clicks on the action in the breadcrumb)
*
- * @returns {Deferred|undefined}
+ * @returns {Promise|undefined}
*/
willRestore: function () {},
@@ -89,14 +89,14 @@ var ActionMixin = {
* example, if the user has edited a form, maybe we should ask him if we
* can discard all his changes when we switch to another action. In that
* case, the action manager will call this method. If the returned
- * deferred is succesfully resolved, then we can destroy the current action,
+ * promise is succesfully resolved, then we can destroy the current action,
* otherwise, we need to stop.
*
- * @returns {Deferred} resolved if the action can be removed, rejected
+ * @returns {Promise} resolved if the action can be removed, rejected
* otherwise
*/
canBeRemoved: function () {
- return $.when();
+ return Promise.resolve();
},
/**
* This function is called when the current state of the action
diff --git a/addons/web/static/src/js/chrome/loading.js b/addons/web/static/src/js/chrome/loading.js
index 6c7f102231b..865aa081bf0 100644
--- a/addons/web/static/src/js/chrome/loading.js
+++ b/addons/web/static/src/js/chrome/loading.js
@@ -26,6 +26,8 @@ var Loading = Widget.extend({
this._super(parent);
this.count = 0;
this.blocked_ui = false;
+ },
+ start: function() {
core.bus.on('rpc_request', this, this.request_call);
core.bus.on("rpc_response", this, this.response_call);
core.bus.on("rpc_response_failed", this, this.response_call);
diff --git a/addons/web/static/src/js/chrome/menu.js b/addons/web/static/src/js/chrome/menu.js
index 8722724c9a6..552dfce811c 100644
--- a/addons/web/static/src/js/chrome/menu.js
+++ b/addons/web/static/src/js/chrome/menu.js
@@ -64,20 +64,22 @@ var Menu = Widget.extend({
// Apps Menu
this._appsMenu = new AppsMenu(self, this.menu_data);
- this._appsMenu.appendTo(this.$menu_apps);
+ var appsMenuProm = this._appsMenu.appendTo(this.$menu_apps);
// Systray Menu
this.systray_menu = new SystrayMenu(this);
- this.systray_menu.attachTo(this.$('.o_menu_systray'));
-
- dom.initAutoMoreMenu(this.$section_placeholder, {
+ var systrayMenuProm = this.systray_menu.attachTo(this.$('.o_menu_systray')).then(function() {
+ dom.initAutoMoreMenu(self.$section_placeholder, {
maxWidth: function () {
return self.$el.width() - (self.$menu_apps.outerWidth(true) + self.$menu_brand_placeholder.outerWidth(true) + self.systray_menu.$el.outerWidth(true));
},
sizeClass: 'SM',
+ });
});
- return this._super.apply(this, arguments);
+
+
+ return Promise.all([this._super.apply(this, arguments), appsMenuProm, systrayMenuProm]);
},
change_menu_section: function (primary_menu_id) {
if (!this.$menu_sections[primary_menu_id]) {
diff --git a/addons/web/static/src/js/chrome/pager.js b/addons/web/static/src/js/chrome/pager.js
index c7f22a6f2c9..86700d93374 100644
--- a/addons/web/static/src/js/chrome/pager.js
+++ b/addons/web/static/src/js/chrome/pager.js
@@ -28,7 +28,7 @@ var Pager = Widget.extend({
* @param {boolean} [options.can_edit] editable feature of the pager
* @param {boolean} [options.single_page_hidden] (not) to display the pager
* if only one page
- * @param {function} [options.validate] callback returning a Deferred to
+ * @param {function} [options.validate] callback returning a Promise to
* validate changes
*/
init: function (parent, size, current_min, limit, options) {
@@ -46,7 +46,7 @@ var Pager = Widget.extend({
can_edit: true, // editable
single_page_hidden: false, // displayed even if there is a single page
validate: function() {
- return $.Deferred().resolve();
+ return Promise.resolve();
},
withAccessKey: true, // can be disabled, for example, for x2m widgets
});
@@ -55,7 +55,7 @@ var Pager = Widget.extend({
/**
* Renders the pager
*
- * @returns {jQuery.Deferred}
+ * @returns {Promise}
*/
start: function () {
this.$value = this.$('.o_pager_value');
@@ -216,7 +216,6 @@ var Pager = Widget.extend({
}
self.trigger('pager_changed', _.clone(self.state));
}
- }).always(function() {
// Render the pager's new state (removes the input)
self._render();
});
diff --git a/addons/web/static/src/js/chrome/sidebar.js b/addons/web/static/src/js/chrome/sidebar.js
index 5cf6005a788..b7883cbb0f7 100644
--- a/addons/web/static/src/js/chrome/sidebar.js
+++ b/addons/web/static/src/js/chrome/sidebar.js
@@ -153,7 +153,7 @@ var Sidebar = Widget.extend({
action_id: item.action.id,
context: context,
},
- }).done(function (result) {
+ }).then(function (result) {
result.context = new Context(
result.context || {}, activeIdsContext)
.set_eval_context(context);
diff --git a/addons/web/static/src/js/chrome/systray_menu.js b/addons/web/static/src/js/chrome/systray_menu.js
index 24fd02a3736..fd214c0b650 100644
--- a/addons/web/static/src/js/chrome/systray_menu.js
+++ b/addons/web/static/src/js/chrome/systray_menu.js
@@ -16,20 +16,19 @@ var SystrayMenu = Widget.extend({
this._super(parent);
this.items = [];
this.widgets = [];
- this.load = $.Deferred();
},
/**
* @override
- * @returns {Deferred}
+ * @returns {Promise}
*/
start: function () {
var self = this;
self._super.apply(this, arguments);
self._loadItems();
- $.when.apply($, self.items).always(function () {
- self.load.resolve();
+
+ return new Promise(function (resolve, reject) {
+ Promise.all(self.items).then(resolve).guardedCatch(resolve);
});
- return self.load;
},
//--------------------------------------------------------------------------
diff --git a/addons/web/static/src/js/chrome/user_menu.js b/addons/web/static/src/js/chrome/user_menu.js
index a066b661fb2..2cc39b4d6bd 100644
--- a/addons/web/static/src/js/chrome/user_menu.js
+++ b/addons/web/static/src/js/chrome/user_menu.js
@@ -22,7 +22,7 @@ var UserMenu = Widget.extend({
/**
* @override
- * @returns {Deferred}
+ * @returns {Promise}
*/
start: function () {
var self = this;
@@ -36,7 +36,7 @@ var UserMenu = Widget.extend({
var $avatar = self.$('.oe_topbar_avatar');
if (!session.uid) {
$avatar.attr('src', $avatar.data('default-src'));
- return $.when();
+ return Promise.resolve();
}
var topbar_name = session.name;
if (session.debug) {
@@ -67,7 +67,7 @@ var UserMenu = Widget.extend({
.then(function (url) {
framework.redirect(url);
})
- .fail(function (result, ev){
+ .guardedCatch(function (result, ev){
ev.preventDefault();
framework.redirect('https://accounts.odoo.com/account');
});
@@ -100,7 +100,7 @@ var UserMenu = Widget.extend({
model: "res.users",
method: "action_get"
})
- .done(function (result) {
+ .then(function (result) {
result.res_id = session.uid;
self.do_action(result);
});
diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js
index 0688adc362f..392d534f372 100644
--- a/addons/web/static/src/js/chrome/web_client.js
+++ b/addons/web/static/src/js/chrome/web_client.js
@@ -111,7 +111,7 @@ return AbstractWebClient.extend({
instanciate_menu_widgets: function () {
var self = this;
- var defs = [];
+ var proms = [];
return this.load_menus().then(function (menuData) {
self.menu_data = menuData;
@@ -122,8 +122,8 @@ return AbstractWebClient.extend({
self.menu.destroy();
}
self.menu = new Menu(self, menuData);
- defs.push(self.menu.prependTo(self.$el));
- return $.when.apply($, defs);
+ proms.push(self.menu.prependTo(self.$el));
+ return Promise.all(proms);
});
},
@@ -133,7 +133,7 @@ return AbstractWebClient.extend({
on_hashchange: function (event) {
if (this._ignore_hashchange) {
this._ignore_hashchange = false;
- return $.when();
+ return Promise.resolve();
}
var self = this;
@@ -181,48 +181,51 @@ return AbstractWebClient.extend({
return this.menu_dm.add(data_manager.load_action(ev.data.action_id))
.then(function (result) {
return self.action_mutex.exec(function () {
- var completed = $.Deferred();
- var options = _.extend({}, ev.data.options, {
- clear_breadcrumbs: true,
- action_menu_id: ev.data.menu_id,
- });
- $.when(self._openMenu(result, options)).fail(function () {
- completed.resolve();
- }).done(function () {
- self._on_app_clicked_done(ev)
- .then(completed.resolve.bind(completed))
- .fail(completed.reject.bind(completed));
+ 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);
});
- setTimeout(function () {
- completed.resolve();
- }, 2000);
return completed;
});
});
},
_on_app_clicked_done: function (ev) {
core.bus.trigger('change_menu_section', ev.data.menu_id);
- return $.Deferred().resolve();
+ return Promise.resolve();
},
on_menu_clicked: function (ev) {
var self = this;
return this.menu_dm.add(data_manager.load_action(ev.data.action_id))
.then(function (result) {
- return self.action_mutex.exec(function () {
- var completed = $.Deferred();
- $.when(self._openMenu(result, {
- clear_breadcrumbs: true,
- })).always(function () {
- completed.resolve();
- });
+ self.$el.removeClass('o_mobile_menu_opened');
- setTimeout(function () {
- completed.resolve();
- }, 2000);
+ 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;
});
- }).always(function () {
+ }).guardedCatch(function () {
self.$el.removeClass('o_mobile_menu_opened');
});
},
@@ -233,7 +236,7 @@ return AbstractWebClient.extend({
* @private
* @param {Object} action
* @param {Object} options
- * @returns {Deferred}
+ * @returns {Promise}
*/
_openMenu: function (action, options) {
return this.do_action(action, options);