diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-05-25 14:34:18 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-05-25 14:34:18 +0200 |
| commit | 37eed7c509fb5846c89ef37046df4b3cab299719 (patch) | |
| tree | f84141132c09ddafa7922375a84d5bf072265d04 /addons/web/static/src/js/views | |
| parent | 943075fd94eec2bc61b751e8828e3bd69054b2f8 (diff) | |
| parent | 58e35522468d1d4c0674518f785a32be56d2c1a2 (diff) | |
[MERGE] forward port branch saas-11.2 up to 58e35522468
Diffstat (limited to 'addons/web/static/src/js/views')
| -rw-r--r-- | addons/web/static/src/js/views/abstract_controller.js | 7 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 48 |
2 files changed, 46 insertions, 9 deletions
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js index decaf1884b2..a3a9e04f30c 100644 --- a/addons/web/static/src/js/views/abstract_controller.js +++ b/addons/web/static/src/js/views/abstract_controller.js @@ -12,6 +12,7 @@ odoo.define('web.AbstractController', function (require) { * reading localstorage, ...) has to go through the controller. */ +var concurrency = require('web.concurrency'); var ControlPanelMixin = require('web.ControlPanelMixin'); var core = require('web.core'); var AbstractAction = require('web.AbstractAction'); @@ -54,6 +55,8 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, { this.controllerID = params.controllerID; this.initialState = params.initialState; + // use a DropPrevious to correctly handle concurrent updates + this.dp = new concurrency.DropPrevious(); // those arguments are temporary, they won't be necessary as soon as the // ControlPanel will be handled by the View this.displayName = params.displayName; @@ -232,11 +235,11 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, { var self = this; var shouldReload = (options && 'reload' in options) ? options.reload : true; var def = shouldReload ? this.model.reload(this.handle, params) : $.when(); - return def.then(function (handle) { + return this.dp.add(def).then(function (handle) { self.handle = handle || self.handle; // update handle if we reloaded var state = self.model.get(self.handle); var localState = self.renderer.getLocalState(); - return self.renderer.updateState(state, params).then(function () { + return self.dp.add(self.renderer.updateState(state, params)).then(function () { self.renderer.setLocalState(localState); self._update(state); }); diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 9c38ecc3a58..1e684d01287 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1559,8 +1559,10 @@ var BasicModel = AbstractModel.extend({ rec = self._makeDataPoint(params); list._cache[rec.res_id] = rec.id; } - - rec._noAbandon = true; + // Do not abandon the record if it has been created + // from `default_get`. The list has a savepoint only + // after having fully executed `default_get`. + rec._noAbandon = !list._savePoint; list._changes.push({operation: 'ADD', id: rec.id}); if (command[0] === 1) { list._changes.push({operation: 'UPDATE', id: rec.id}); @@ -1979,6 +1981,9 @@ var BasicModel = AbstractModel.extend({ var records = []; var ids = []; list = this._applyX2ManyOperations(list); + if (_.isEmpty(list.data)) { + return $.when(); + } _.each(list.data, function (localId) { var record = self.localData[localId]; var data = record._changes || record.data; @@ -1992,13 +1997,16 @@ var BasicModel = AbstractModel.extend({ return this._rpc({ model: model, method: 'name_get', - args: [ids], + args: [_.uniq(ids)], context: list.context, }) .then(function (name_gets) { - for (var i = 0; i < name_gets.length; i++) { - records[i].data.display_name = name_gets[i][1]; - } + _.each(records, function (record) { + var nameGet = _.find(name_gets, function (nameGet) { + return nameGet[0] === record.data.id; + }); + record.data.display_name = nameGet[1]; + }); }); }, /** @@ -2484,7 +2492,16 @@ var BasicModel = AbstractModel.extend({ var self = this; var def; if (list.static) { - def = this._readUngroupedList(list); + def = this._readUngroupedList(list).then(function () { + if (list.parentID && self.isNew(list.parentID)) { + // list from a default_get, so fetch display_name for many2one fields + var many2ones = self._getMany2OneFieldNames(list); + var defs = _.map(many2ones, function (name) { + return self._fetchNameGets(list, name); + }); + return $.when.apply($, defs); + } + }); } else { def = this._searchReadUngroupedList(list); } @@ -3053,6 +3070,23 @@ var BasicModel = AbstractModel.extend({ return Object.keys(fieldsInfo && fieldsInfo[viewType] || {}); }, /** + * Get many2one fields names in a datapoint. This is useful in order to + * fetch their names in the case of a default_get. + * + * @private + * @param {Object} datapoint a valid resource object + * @returns {string[]} list of field names that are many2one + */ + _getMany2OneFieldNames: function (datapoint) { + var many2ones = []; + _.each(datapoint.fields, function (field, name) { + if (field.type === 'many2one') { + many2ones.push(name); + } + }); + return many2ones; + }, + /** * Evaluate the record evaluation context. This method is supposed to be * called by _getEvalContext. It basically only generates a dictionary of * current values for the record, with commands for x2manys fields. |
