summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-05-30 12:18:52 +0200
committerChristophe Simonis <chs@odoo.com>2018-05-30 12:18:52 +0200
commite008ef302a1b3fc584d4f0fb9956d237947f17d5 (patch)
tree7976948d25c1aa7aa23123ccabb37b5eaae8e8e3 /addons/web/static/src
parentf36e6917bd73a56dc0c7468b4849920df4088154 (diff)
parent53300648edef8f87bfd0bff6b52536efdd1cc82c (diff)
[MERGE] forward port branch saas-11.3 up to 53300648ede
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/chrome/control_panel.js5
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js15
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js18
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js20
4 files changed, 52 insertions, 6 deletions
diff --git a/addons/web/static/src/js/chrome/control_panel.js b/addons/web/static/src/js/chrome/control_panel.js
index 558dde933e9..4104f37bd3e 100644
--- a/addons/web/static/src/js/chrome/control_panel.js
+++ b/addons/web/static/src/js/chrome/control_panel.js
@@ -80,6 +80,9 @@ var ControlPanel = Widget.extend({
}
this.bus = new Bus(this);
+ // the updateIndex is used to prevent concurrent updates of the control
+ // panel depending on asynchronous code to be executed in the wrong order
+ this.bus.updateIndex = 0;
this.bus.on("update", this, this.update);
},
/**
@@ -126,6 +129,8 @@ var ControlPanel = Widget.extend({
* elements that are not in status.cp_content
*/
update: function(status, options) {
+ this.bus.updateIndex++;
+
this._toggle_visibility(!status.hidden);
// Don't update the ControlPanel in headless mode as the views have
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index 2f9957737ae..bf4f3a616f3 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -235,11 +235,26 @@ 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();
+ // we check here that the updateIndex of the control panel hasn't changed
+ // between the start of the update request and the moment the controller
+ // asks the control panel to update itself ; indeed, it could happen that
+ // another action/controller is executed during this one reloads itself,
+ // and if that one finishes first, it replaces this controller in the DOM,
+ // and this controller should no longer update the control panel.
+ // note that this won't be necessary as soon as each controller will have
+ // its own control panel
+ var cpUpdateIndex = this.cp_bus && this.cp_bus.updateIndex;
return this.dp.add(def).then(function (handle) {
+ if (self.cp_bus && cpUpdateIndex !== self.cp_bus.updateIndex) {
+ return;
+ }
self.handle = handle || self.handle; // update handle if we reloaded
var state = self.model.get(self.handle);
var localState = self.renderer.getLocalState();
return self.dp.add(self.renderer.updateState(state, params)).then(function () {
+ if (self.cp_bus && cpUpdateIndex !== self.cp_bus.updateIndex) {
+ return;
+ }
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 cc3dbd67595..6cb91d152d0 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -886,6 +886,15 @@ var BasicModel = AbstractModel.extend({
// x2Many case: the new record has been stored in _changes, as a
// command so we remove the command(s) related to that record
parent._changes = _.filter(parent._changes, function (change) {
+ if (change.id === elementID &&
+ change.operation === 'ADD' && // For now, only an ADD command increases limits
+ parent.tempLimitIncrement) {
+ // The record will be deleted from the _changes.
+ // So we won't be passing into the logic of _applyX2ManyOperations anymore
+ // implying that we have to cancel out the effects of an ADD command here
+ parent.tempLimitIncrement--;
+ parent.limit--;
+ }
return change.id !== elementID;
});
} else {
@@ -3138,6 +3147,15 @@ var BasicModel = AbstractModel.extend({
// when sent to the server, the x2manys values must be a list
// of commands in a context, but the list of ids in a domain
ids.toJSON = _generateX2ManyCommands.bind(null, fieldName);
+ } else if (field.type === 'one2many') { // Ids are evaluated as a list of ids
+ /* Filtering out virtual ids from the ids list
+ * The server will crash if there are virtual ids in there
+ * The webClient doesn't do literal id list comparison like ids == list
+ * Only relevant in o2m: m2m does create actual records in db
+ */
+ ids = _.filter(ids, function (id) {
+ return typeof id !== 'string';
+ });
}
context[fieldName] = ids;
}
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js
index 24b053a7bbe..9834c9c18de 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -661,15 +661,23 @@ var BasicRenderer = AbstractRenderer.extend({
// Prepare widget rendering and save the related deferred
var def = widget._widgetRenderAndInsert(function () {});
- if (def.state() === 'pending') {
+ var async = def.state() === 'pending';
+ if (async) {
this.defs.push(def);
}
+ var $el = async ? $('<div>') : widget.$el;
- // handle other attributes/modifiers
- this._handleAttributes(widget.$el, node);
- this._registerModifiers(node, record, widget);
- widget.$el.addClass('o_widget');
- return widget.$el;
+ var self = this;
+ def.then(function () {
+ self._handleAttributes(widget.$el, node);
+ self._registerModifiers(node, record, widget);
+ widget.$el.addClass('o_widget');
+ if (async) {
+ $el.replaceWith(widget.$el);
+ }
+ });
+
+ return $el;
},
/**