From 7524b8ef923692ac8498a4ac25365424b17b607a Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Thu, 18 May 2017 15:25:01 +0200 Subject: [FIX] web: allow passing multiple ids in `call_button` Passing multiple ids wasn't correctly handled as the argument `record_id` was wrapped in a list of list, which is not hashable. The wrapping is now handled by the caller. --- addons/web/static/src/js/views/basic/basic_controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/src/js/views/basic/basic_controller.js') diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 1e0187b348e..4c8363a81b1 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -258,7 +258,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { context: record.getContext({additionalContext: attrs.context}), }), model: record.model, - record_id: recordID, + res_ids: [recordID], on_closed: function (reason) { if (!_.isObject(reason)) { reload(); -- cgit v1.2.3 From 3aad756d32ece364ccbe0953d6acebdbe7581f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Sun, 21 May 2017 09:23:27 +0200 Subject: [FIX] web: properly handles ESC in editable lists It is not really easy to handle discard operations. We need to handle the discard in editable lists, and in x2manys. This is not exactly the same code, but most of this was done by moving the discard method from the formcontroller to the basic controller. With this commit, the user can now discard the changes for the current record by pressing ESC. If the record is new, it will remove it, if not, it will ask for confirmation before. --- .../static/src/js/views/basic/basic_controller.js | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'addons/web/static/src/js/views/basic/basic_controller.js') diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 4c8363a81b1..3b24df19e3e 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -18,6 +18,7 @@ var _t = core._t; var BasicController = AbstractController.extend(FieldManagerMixin, { custom_events: _.extend({}, AbstractController.prototype.custom_events, FieldManagerMixin.custom_events, { + discard_changes: '_onDiscardChanges', reload: '_onReload', sidebar_data_asked: '_onSidebarDataAsked', translate: '_onTranslate', @@ -456,6 +457,31 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { // Handlers //-------------------------------------------------------------------------- + /** + * Called when a list element asks to discard the changes made to one of + * its rows. It can happen with a x2many (if we are in a form view) or with + * a list view. + * + * @private + * @param {OdooEvent} ev + */ + _onDiscardChanges: function (ev) { + var self = this; + ev.stopPropagation(); + var recordID = ev.data.recordID; + this.discardChanges(recordID) + .done(function () { + if (self.model.isNew(recordID)) { + self._abandonRecord(recordID); + } + // TODO this will tell the renderer to rerender the widget that + // asked for the discard but will unfortunately lose the click + // made on another row if any + self._confirmChange(self.handle, [ev.data.fieldName], ev) + .always(ev.data.onSuccess); + }) + .fail(ev.data.onFailure); + }, /** * Forces to save directly the changes if the controller is in readonly, * because in that case the changes come from widgets that are editable even -- cgit v1.2.3 From 3460bda5203ce365bdc56a79ef906217219acb6d Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Tue, 16 May 2017 11:35:23 +0200 Subject: [FIX] web: disable stat buttons until action resolution Previously, it was possible to click multiple times on stat buttons while still waiting for the result of a previous button click. This could end up with the web client in strange states or, worse, lead to tracebacks. Because of this, we decided to disable the buttons once one of them is clicked and restore them afterwards. By doing this, we encovered a place in the code where a failed deferred would not be properly forwarded back to the caller, which meant, in our case, that the buttons would not be enabled back in case the action failed. This is now fixed. Initial methods to fix this issue used to break the test below. Because the label of the assertion this used to break was contradictory with the value it was actually expecting, we decided to fix it as well. --- addons/web/static/src/js/views/basic/basic_controller.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_controller.js') diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 3b24df19e3e..8d35e7f8fcd 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -248,9 +248,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { var self = this; var def = $.Deferred(); var reload = function () { - if (!self.isDestroyed()) { - self.reload(); - } + return self.isDestroyed() ? $.when() : self.reload(); }; record = record || this.model.get(this.handle); var recordID = record.data.id; @@ -262,10 +260,14 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { res_ids: [recordID], on_closed: function (reason) { if (!_.isObject(reason)) { - reload(); + reload(reason); } }, - on_fail: reload, + on_fail: function (reason) { + reload().always(function() { + def.reject(reason); + }) + }, on_success: def.resolve.bind(def), }); return this.alive(def); -- cgit v1.2.3 From 374295bf849680e9173475bdf01794f2a1935de3 Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Wed, 17 May 2017 14:33:56 +0200 Subject: [FIX] web: save should not re-read fields if none were changed Previously, it used to reload its data when the user clicked multiple times on save, even though there were only changed fields during the first initial save, all the other queued ones have no changes at all and, as such, should not trigger additional reloads. --- addons/web/static/src/js/views/basic/basic_controller.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_controller.js') diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 8d35e7f8fcd..f58b858db9e 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -388,18 +388,19 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { // Note: it is the model's job to do nothing if there is nothing to save if (this.canBeSaved(recordID)) { var self = this; - var def = this.model.save(recordID, { // Save then leave edit mode + var saveDef = this.model.save(recordID, { // Save then leave edit mode reload: options.reload, savePoint: options.savePoint, }); if (!options.stayInEdit) { - def = def.then(function (fieldNames) { - return self._confirmSave(recordID).then(function () { + saveDef = saveDef.then(function (fieldNames) { + var def = fieldNames.length ? self._confirmSave(recordID) : self._setMode('readonly'); + return def.then(function () { return fieldNames; }); }); } - return def; + return saveDef; } else { return $.Deferred().reject(); // Cannot be saved } -- cgit v1.2.3 From 23613b411feb6571c0f2907d8c88a7e8f8e39d87 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 31 May 2017 08:29:00 +0200 Subject: [FIX] web: x2m editable list: wait for onchanges ... before saving a line. Suppose that we have an editable list with one required field (e.g. many2one) with an onchange. We add a record and select a value for the many2one. Before the onchange returns, we click again on 'Add an item'. If we don't wait for the onchange to return before unselecting the row (i.e. before saving it), a confirm dialog asking if the changes can be discarded opens, because the line isn't valid yet. This could easily be reproduced on the sale_order form view, with some throttling. This rev. ensures that we wait for the onchange to return before saving the line, and thus before creating a new line. --- addons/web/static/src/js/views/basic/basic_controller.js | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'addons/web/static/src/js/views/basic/basic_controller.js') diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index f58b858db9e..9f767799851 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -19,6 +19,7 @@ var _t = core._t; var BasicController = AbstractController.extend(FieldManagerMixin, { custom_events: _.extend({}, AbstractController.prototype.custom_events, FieldManagerMixin.custom_events, { discard_changes: '_onDiscardChanges', + mutexify: '_onMutexify', reload: '_onReload', sidebar_data_asked: '_onSidebarDataAsked', translate: '_onTranslate', @@ -499,6 +500,14 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { } FieldManagerMixin._onFieldChanged.apply(this, arguments); }, + /** + * @private + * @param {OdooEvent} ev + * @param {function} ev.data.action the function to execute in the mutex + */ + _onMutexify: function (ev) { + this.mutex.exec(ev.data.action); + }, /** * When a reload event triggers up, we need to reload the full view. * For example, after a form view dialog saved some data. -- cgit v1.2.3 From f9a1241721d1457dd7ddd0eebb1ec0ba4fba3225 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 31 May 2017 08:55:24 +0200 Subject: [FIX] web: editable list: don't create invalid records Clicking multiple times on 'Create' (in main list views) or 'Add an item' (in o2m lists) might create invalid rows (i.e. rows with required fields unset). Creating a new record requires two sequential RPCs: a default_get and an onchange (only if there is an onchange of one of the record's field). When clicking twice to create a new record, that sequence of RPCs is done twice in parallel, after unselecting the current row (i.e. saving it if it is valid). However, in both cases, there is no line to unselect yet (as both operations are done basically simultaneously). When the first onchange returns, a first new record is added to the list. When the second returns, the second one is added and takes the edition, leaving the first one, invalid, in the list. This rev. ensures this doesn't happen by preventing concurrent record creation. --- .../static/src/js/views/basic/basic_controller.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'addons/web/static/src/js/views/basic/basic_controller.js') diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 9f767799851..53e5be8ff6e 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -309,6 +309,26 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { doIt(); } }, + /** + * Disables buttons so that they can't be clicked anymore. + * + * @private + */ + _disableButtons: function () { + if (this.$buttons) { + this.$buttons.find('button').attr('disabled', true); + } + }, + /** + * Enables buttons so they can be clicked again. + * + * @private + */ + _enableButtons: function () { + if (this.$buttons) { + this.$buttons.find('button').removeAttr('disabled'); + } + }, /** * Returns the new sidebar env * -- cgit v1.2.3