diff --git a/addons/web/doc/client_action.rst b/addons/web/doc/client_action.rst index 9b729e228a6..4852400df10 100644 --- a/addons/web/doc/client_action.rst +++ b/addons/web/doc/client_action.rst @@ -83,18 +83,19 @@ method. As required by :js:class:`~openerp.web.Widget`'s contract, if :js:func:`~openerp.web.Widget.start()` executes any asynchronous - code it should return a ``$.Deferred`` so callers know when it's + code it should return a ``Promise`` so callers know when it's ready for interaction. .. code-block:: javascript start: function () { - return $.when( + return Promise.all([ this._super(), // Simply read the res.widget object this action should display new instance.web.Model('res.widget').call( 'read', [[this.widget_id], ['title']]) - .then(this.proxy('on_widget_loaded')); + .then(this.proxy('on_widget_loaded') + ]); } The client action can then behave exactly as it wishes to within its diff --git a/addons/web/static/src/js/_deprecated/data.js b/addons/web/static/src/js/_deprecated/data.js index 984f0bbaddb..acac959fcc8 100644 --- a/addons/web/static/src/js/_deprecated/data.js +++ b/addons/web/static/src/js/_deprecated/data.js @@ -101,7 +101,7 @@ var Query = Class.extend({ * Fetches the first record matching the query, or null * * @param {Object} [options] additional options for the rpc() method - * @returns {jQuery.Deferred} + * @returns {Promise} */ first: function (options) { var self = this; @@ -115,7 +115,7 @@ var Query = Class.extend({ * Fetches all records matching the query * * @param {Object} [options] additional options for the rpc() method - * @returns {jQuery.Deferred>} + * @returns {Promise>} */ all: function (options) { return this._execute(options); @@ -123,10 +123,10 @@ var Query = Class.extend({ /** * Fetches the number of records matching the query in the database * - * @returns {jQuery.Deferred} + * @returns {Promise} */ count: function () { - if (this._count !== undefined) { return $.when(this._count); } + if (this._count !== undefined) { return Promise.resolve(this._count); } return this._model.call( 'search_count', [this._filter], { context: this._model.context(this._context)}); @@ -367,11 +367,12 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * @param {Array} ids identifiers of the records to read * @param {Array} [fields] fields to read and return, by default all fields are returned * @param {Object} [options] - * @returns {$.Deferred} + * @returns {Promise} */ read_ids: function (ids, fields, options) { - if (_.isEmpty(ids)) - return $.Deferred().resolve([]); + if (_.isEmpty(ids)) { + return Promise.resolve([]); + } options = options || {}; var method = 'read'; @@ -405,7 +406,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * @params {Object} [options] * @param {Number} [options.offset=0] The index from which selected records should be returned * @param {Number} [options.limit=null] The maximum number of records to return - * @returns {$.Deferred} + * @returns {Promise} */ read_slice: function (fields, options) { var self = this; @@ -414,21 +415,23 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { .limit(options.limit || false) .offset(options.offset || 0) .all(); - return this.orderer.add(query).done(function (records) { + var prom = this.orderer.add(query); + prom.then(function (records) { self.ids = _(records).pluck('id'); }); + return prom; }, /** * Reads the current dataset record (from its index) * * @params {Array} [fields] fields to read and return, by default all fields are returned * @param {Object} [options.context] context data to add to the request payload, on top of the DataSet's own context - * @returns {$.Deferred} + * @returns {Promise} */ read_index: function (fields, options) { options = options || {}; return this.read_ids([this.ids[this.index]], fields, options).then(function (records) { - if (_.isEmpty(records)) { return $.Deferred().reject().promise(); } + if (_.isEmpty(records)) { return Promise.reject(); } return records[0]; }); }, @@ -437,7 +440,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * * @param {Array} [fields] fields to get default values for, by default all defaults are read * @param {Object} [options.context] context data to add to the request payload, on top of the DataSet's own context - * @returns {$.Deferred} + * @returns {Promise} */ default_get: function (fields, options) { options = options || {}; @@ -451,15 +454,17 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * @param {Object} options Dictionary that can contain the following keys: * - readonly_fields: Values from readonly fields that were updated by * on_changes. Only used by the BufferedDataSet to make the o2m work correctly. - * @returns {$.Deferred} + * @returns {Promise} */ create: function (data, options) { var self = this; - return this._model.call('create', [data], { + var prom = this._model.call('create', [data], { context: this.get_context() - }).done(function () { + }); + prom.then(function () { self.trigger('dataset_changed', data, options); }); + return prom; }, /** * Saves the provided data in an existing db record @@ -470,16 +475,18 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * - context: The context to use in the server-side call. * - readonly_fields: Values from readonly fields that were updated by * on_changes. Only used by the BufferedDataSet to make the o2m work correctly. - * @returns {$.Deferred} + * @returns {Promise} */ write: function (id, data, options) { options = options || {}; var self = this; - return this._model.call('write', [[id], data], { + var prom = this._model.call('write', [[id], data], { context: this.get_context(options.context) - }).done(function () { + }); + prom.then(function () { self.trigger('dataset_changed', id, data, options); }); + return prom; }, /** * Deletes an existing record from the database @@ -488,11 +495,13 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { */ unlink: function (ids) { var self = this; - return this._model.call('unlink', [ids], { + var prom = this._model.call('unlink', [ids], { context: this.get_context() - }).done(function () { + }); + prom.then(function () { self.trigger('dataset_changed', ids); }); + return prom; }, /** * Calls an arbitrary RPC method @@ -501,7 +510,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * @param {Array} [args] arguments to pass to the method * @param {Function} callback * @param {Function} error_callback - * @returns {$.Deferred} + * @returns {Promise} */ call: function (method, args) { return this._model.call(method, args); @@ -511,7 +520,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * * @param {String} method * @param {Array} [args] - * @returns {$.Deferred} + * @returns {Promise} */ call_button: function (method, args) { return this._model.call_button(method, args); @@ -520,7 +529,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * Fetches the "readable name" for records, based on intrinsic rules * * @param {Array} ids - * @returns {$.Deferred} + * @returns {Promise} */ name_get: function (ids) { return this._model.call('name_get', [ids], {context: this.get_context()}); @@ -532,7 +541,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * @param {String} [operator='ilike'] matching operator to use with the provided name value * @param {Number} [limit=0] maximum number of matches to return * @param {Function} callback function to call with name_search result - * @returns {$.Deferred} + * @returns {Promise} */ name_search: function (name, domain, operator, limit) { return this._model.call('name_search', { @@ -603,7 +612,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, { * Resequence records. * * @param {Array} ids identifiers of the records to resequence - * @returns {$.Deferred} + * @returns {Promise} */ resequence: function (ids, options) { options = options || {}; @@ -643,7 +652,7 @@ var DataSetStatic = DataSet.extend({ unlink: function (ids) { this.set_ids(_.without.apply(null, [this.ids].concat(ids))); this.trigger('unlink', ids); - return $.Deferred().resolve({result: true}); + return Promise.resolve({result: true}); }, }); @@ -674,7 +683,7 @@ var DataSetSearch = DataSet.extend({ * @param {Array} [options.domain] domain data to add to the request payload, ANDed with the dataset's domain * @param {Number} [options.offset=0] The index from which selected records should be returned * @param {Number} [options.limit=null] The maximum number of records to return - * @returns {$.Deferred} + * @returns {Promise} */ read_slice: function (fields, options) { options = options || {}; @@ -686,11 +695,13 @@ var DataSetSearch = DataSet.extend({ .limit(options.limit || false); q = q.order_by.apply(q, this._sort); - return this.orderer.add(q.all()).done(function (records) { + var prom = this.orderer.add(q.all()); + prom.then(function (records) { // FIXME: not sure about that one, *could* have discarded count - q.count().done(function (count) { self._length = count; }); + q.count().then(function (count) { self._length = count; }); self.ids = _(records).pluck('id'); }); + return prom; }, get_domain: function (other_domain) { return this._model.domain(other_domain); @@ -717,10 +728,12 @@ var DataSetSearch = DataSet.extend({ }, unlink: function (ids, callback, error_callback) { var self = this; - return this._super(ids).done(function () { + var prom = this._super(ids); + prom.then(function () { self.remove_ids( ids); self.trigger("dataset_changed", ids, callback, error_callback); }); + return prom; }, size: function () { if (this._length !== null) { @@ -801,7 +814,7 @@ var Model = Class.extend({ * @param {Array} [args] positipyEvalonal arguments * @param {Object} [kwargs] keyword arguments * @param {Object} [options] additional options for the rpc() method - * @returns {jQuery.Deferred<>} call result + * @returns {Promise<>} call result */ call: function (method, args, kwargs, options) { args = args || []; diff --git a/addons/web/static/src/js/apps.js b/addons/web/static/src/js/apps.js index aadcc700984..739317337ba 100644 --- a/addons/web/static/src/js/apps.js +++ b/addons/web/static/src/js/apps.js @@ -22,20 +22,21 @@ var Apps = AbstractAction.extend({ }, get_client: function() { - // return the client via a deferred, resolved or rejected depending if + // return the client via a promise, resolved or rejected depending if // the remote host is available or not. var check_client_available = function(client) { - var d = $.Deferred(); var i = new Image(); - i.onerror = function() { - d.reject(client); - }; - i.onload = function() { - d.resolve(client); - }; + var def = new Promise(function (resolve, reject) { + i.onerror = function() { + reject(client); + }; + i.onload = function() { + resolve(client); + }; + }); var ts = new Date().getTime(); i.src = _.str.sprintf('%s/web/static/src/img/sep-a.gif?%s', client.origin, ts); - return d.promise(); + return def; }; if (apps_client) { return check_client_available(apps_client); @@ -105,58 +106,56 @@ var Apps = AbstractAction.extend({ start: function() { var self = this; - var def = $.Deferred(); - self.get_client().then(function(client) { - self.client = client; + return new Promise(function (resolve, reject) { + self.get_client().then(function (client) { + self.client = client; - var qs = {db: client.dbname}; - if (session.debug) { - qs.debug = session.debug; - } - var u = $.param.querystring(client.origin + "/apps/embed/client", qs); - var css = {width: '100%', height: '750px'}; - self.$ifr = $('