From 2d93553e0dc4966629d0c5fa4e4b789bda8239d9 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Wed, 31 Oct 2012 16:39:46 +0100 Subject: [PATCH 1/6] Redirected onchange and save to a common operation bzr revid: nicolas.vanhoren@openerp.com-20121031153946-zvmoh7g7rtc69pyc --- addons/web/static/src/js/view_form.js | 167 +++++++++++++++----------- 1 file changed, 99 insertions(+), 68 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index e0727b99259..b240c48c14e 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -114,7 +114,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM }); this.is_initialized = $.Deferred(); this.mutating_mutex = new $.Mutex(); - this.on_change_mutex = new $.Mutex(); + this.on_change_list = []; + this.save_list = []; this.reload_mutex = new $.Mutex(); this.__clicked_inside = false; this.__blur_timeout = null; @@ -492,67 +493,72 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM }, do_onchange: function(widget, processed) { var self = this; - return this.on_change_mutex.exec(function() { - try { - var def; - processed = processed || []; - processed.push(widget.name); - var on_change = widget.node.attrs.on_change; - if (on_change) { - var change_spec = self.parse_on_change(on_change, widget); - def = self.rpc('/web/dataset/onchange', { - model: self.dataset.model, - method: change_spec.method, - args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args), - context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1 - }); - } else { - def = $.when({}); - } - return def.pipe(function(response) { - if (widget.field['change_default']) { - var fieldname = widget.name - var value_; - if (response.value && (fieldname in response.value)) { - // Use value from onchange if onchange executed - value_ = response.value[fieldname]; - } else { - // otherwise get form value for field - value_ = self.fields[fieldname].get_value(); - } - var condition = fieldname + '=' + value_; - - if (value_) { - return self.rpc('/web/dataset/call', { - model: 'ir.values', - method: 'get_defaults', - args: [self.model, condition] - }).pipe(function (results) { - if (!results.length) { - return response; - } - if (!response.value) { - response.value = {}; - } - for(var i=0; i Date: Mon, 5 Nov 2012 12:16:35 +0100 Subject: [PATCH 2/6] [IMP] put back commit_value bzr revid: nicolas.vanhoren@openerp.com-20121105111635-5aygxpvlfuxqozu5 --- addons/web/static/src/js/view_form.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index bee3224407a..01eb8237ba2 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2010,6 +2010,11 @@ instance.web.form.FieldInterface = { * Called when the translate button is clicked. */ on_translate: function() {}, + /** + This method is called by the form view before reading on_change values and before saving. It tells + the field to save its value before reading it using get_value(). Must return a deferred. + */ + commit_value: function() {}, }; /** @@ -2153,7 +2158,10 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w } this.$el.attr('style', style); this.$el.css('minHeight', height); - } + }, + commit_value: function() { + return $.when(); + }, }); /** From a4dd3172712ff099cb028681d9843895dad6ef18 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 5 Nov 2012 12:18:19 +0100 Subject: [PATCH 3/6] Now uses commit_value bzr revid: nicolas.vanhoren@openerp.com-20121105111819-g4dovxlob9ivashl --- addons/web/static/src/js/view_form.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 01eb8237ba2..af38352e7f5 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -604,13 +604,23 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM return iterate(); }); } - var save_obj = self.save_list.pop(); - if (save_obj) { - return self._process_save(save_obj).pipe(function() { - return iterate.apply(null, arguments); - }); - } - return $.when.apply($, arguments); + var defs = []; + _.each(self.fields, function(field) { + defs.push(field.commit_value()); + }); + var args = _.toArray(arguments); + return $.when.apply($, defs).pipe(function() { + if (self.on_change_list.length !== 0) { + return iterate(); + } + var save_obj = self.save_list.pop(); + if (save_obj) { + return self._process_save(save_obj).pipe(function() { + return iterate.apply(null, arguments); + }); + } + return $.when.apply($, args); + }); }; return iterate(); }); From cd88f9ec02bd59a7ec1d58ca8e1642a27c429a63 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 5 Nov 2012 16:05:40 +0100 Subject: [PATCH 4/6] modified doc bzr revid: nicolas.vanhoren@openerp.com-20121105150540-yhcfpoiwffv6kjs3 --- addons/web/static/src/js/view_form.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index af38352e7f5..956f0468ded 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2022,7 +2022,7 @@ instance.web.form.FieldInterface = { on_translate: function() {}, /** This method is called by the form view before reading on_change values and before saving. It tells - the field to save its value before reading it using get_value(). Must return a deferred. + the field to save its value before reading it using get_value(). Must return a promise. */ commit_value: function() {}, }; @@ -2265,7 +2265,7 @@ instance.web.form.FieldChar = instance.web.form.AbstractField.extend(instance.we }, focus: function() { this.$('input:first').focus(); - } + }, }); instance.web.form.FieldID = instance.web.form.FieldChar.extend({ From 90484f785867fa3f3b1030a221d8e20d1d5f6549 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 5 Nov 2012 18:14:12 +0100 Subject: [PATCH 5/6] Implemented commit_value in o2m (must still fix problem in list editable, it does not seem to tolerate multiple calls to save) bzr revid: nicolas.vanhoren@openerp.com-20121105171412-g8okue97wjbkeu3t --- addons/web/static/src/js/view_form.js | 55 +++++++++++---------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 956f0468ded..f6aea0eb387 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -616,10 +616,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM var save_obj = self.save_list.pop(); if (save_obj) { return self._process_save(save_obj).pipe(function() { - return iterate.apply(null, arguments); + save_obj.ret = _.toArray(arguments); + return iterate(); }); } - return $.when.apply($, args); + return $.when(); }); }; return iterate(); @@ -802,8 +803,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM */ save: function(prepend_on_create) { var self = this; - this.save_list.push({prepend_on_create: prepend_on_create}); - return this._process_operations(); + var save_obj = {prepend_on_create: prepend_on_create, ret: null}; + this.save_list.push(save_obj); + return this._process_operations().pipe(function() { + return $.when.apply($, save_obj.ret); + }); }, _process_save: function(save_obj) { var self = this; @@ -3284,10 +3288,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({ this.reload_current_view(); }, trigger_on_change: function() { - var tmp = this.doing_on_change; - this.doing_on_change = true; this.trigger('changed_value'); - this.doing_on_change = tmp; }, load_views: function() { var self = this; @@ -3482,7 +3483,6 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({ var self = this; if (!this.dataset) return []; - this.save_any_view(); var val = this.dataset.delete_all ? [commands.delete_all()] : []; val = val.concat(_.map(this.dataset.ids, function(id) { var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;}); @@ -3499,33 +3499,24 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({ this.dataset.to_delete, function(x) { return commands['delete'](x.id);})); }, + commit_value: function() { + return this.save_any_view(); + }, save_any_view: function() { - if (this.doing_on_change) - return false; - return this.session.synchronized_mode(_.bind(function() { - if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view && - this.viewmanager.views[this.viewmanager.active_view] && - this.viewmanager.views[this.viewmanager.active_view].controller) { - var view = this.viewmanager.views[this.viewmanager.active_view].controller; - if (this.viewmanager.active_view === "form") { - if (!view.is_initialized.isResolved()) { - return false; - } - var res = $.when(view.save()); - if (!res.isResolved() && !res.isRejected()) { - console.warn("Asynchronous get_value() is not supported in form view."); - } - return res; - } else if (this.viewmanager.active_view === "list") { - var res = $.when(view.ensure_saved()); - if (!res.isResolved() && !res.isRejected()) { - console.warn("Asynchronous get_value() is not supported in list view."); - } - return res; + if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view && + this.viewmanager.views[this.viewmanager.active_view] && + this.viewmanager.views[this.viewmanager.active_view].controller) { + var view = this.viewmanager.views[this.viewmanager.active_view].controller; + if (this.viewmanager.active_view === "form") { + if (!view.is_initialized.isResolved()) { + return $.when(false); } + return $.when(view.save()); + } else if (this.viewmanager.active_view === "list") { + return $.when(view.ensure_saved()); } - return false; - }, this)); + } + return $.when(false); }, is_syntax_valid: function() { if (! this.viewmanager || ! this.viewmanager.views[this.viewmanager.active_view]) From fd2bb078fb297c59b0359816e5cff5a33dbfc1a7 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 6 Nov 2012 11:38:28 +0100 Subject: [PATCH 6/6] Fixed problem with editable list bzr revid: nicolas.vanhoren@openerp.com-20121106103828-uw6xv1ed7wueii71 --- addons/web/static/src/js/view_form.js | 2 +- addons/web/static/src/js/view_list_editable.js | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index f6aea0eb387..dd9d8fe7c09 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -3739,7 +3739,7 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({ } // FIXME: why isn't there an API for this? if (this.editor.form.$el.hasClass('oe_form_dirty')) { - this.save_edition(); + this.ensure_saved(); return; } this.cancel_edition(); diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 021e5549c18..85465e1c54e 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -12,6 +12,8 @@ openerp.web.list_editable = function (instance) { var self = this; this._super.apply(this, arguments); + this.saving_mutex = new $.Mutex(); + this._force_editability = null; this._context_editable = false; this.editor = this.make_editor(); @@ -162,10 +164,13 @@ openerp.web.list_editable = function (instance) { * @returns {$.Deferred} */ ensure_saved: function () { - if (!this.editor.is_editing()) { - return $.when(); - } - return this.save_edition(); + var self = this; + return this.saving_mutex.exec(function() { + if (!self.editor.is_editing()) { + return $.when(); + } + return self.save_edition(); + }); }, /** * Set up the edition of a record of the list view "inline"