[FIX] web: various small issues in form view onchange/one2many
- Issue: Edit sale.order form view, add new line, change product who have taxes and click quickly on save (with slow network) => error message. Because some deferreds are lost. - reduce number of reads and onchange for x2m widgets - remove before_save method and use commit_value (the issue was that if the before_save and the change trigger an onchange, the onchange deferred is not checked before saving the content.
This commit is contained in:
committed by
Géry Debongnie
parent
bbbf3db581
commit
feeac2a4f1
@@ -833,9 +833,10 @@ var BufferedDataSet = DataSetStatic.extend({
|
||||
});
|
||||
}
|
||||
this.delete_all = false;
|
||||
_.each(_.clone(this.running_reads), function(el) {
|
||||
el.reject();
|
||||
});
|
||||
this.cancel_read();
|
||||
},
|
||||
cancel_read: function () {
|
||||
_.invoke(_.clone(this.running_reads), 'reject');
|
||||
},
|
||||
read_ids: function (ids, fields, options) {
|
||||
// read what is necessary from the server to have ids and the given
|
||||
@@ -897,11 +898,8 @@ var BufferedDataSet = DataSetStatic.extend({
|
||||
});
|
||||
var _super = this._super;
|
||||
this.mutex.exec(function () {
|
||||
_super.call(self, to_get, fields, options).then(function() {
|
||||
def.resolve.apply(def, arguments);
|
||||
}, function() {
|
||||
def.reject.apply(def, arguments);
|
||||
});
|
||||
if (def.state() !== "pending") return;
|
||||
_super.call(self, to_get, fields, options).then(_.bind(def.resolve, def), _.bind(def.reject, def));
|
||||
return def;
|
||||
});
|
||||
return def.then(function(records) {
|
||||
|
||||
@@ -632,12 +632,6 @@ var FieldInterface = {
|
||||
the field to save its value before reading it using get_value(). Must return a promise.
|
||||
*/
|
||||
commit_value: function() {},
|
||||
/*
|
||||
The form view call before_save before save data and if before_save return a deferred,
|
||||
the form view wait that all deferred are resolve or fail.
|
||||
If the deferred is rejected, the field is invalidate
|
||||
*/
|
||||
before_save: function() {},
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -489,8 +489,13 @@ var AbstractManyField = common.AbstractField.extend({
|
||||
}
|
||||
var tmp = this.no_rerender;
|
||||
this.no_rerender = true;
|
||||
this.data_replace(ids.slice());
|
||||
var def = this.data_replace(ids.slice());
|
||||
this.no_rerender = tmp;
|
||||
return def;
|
||||
},
|
||||
|
||||
commit_value: function() {
|
||||
return this.mutex.def;
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -859,13 +864,9 @@ var FieldX2Many = AbstractManyField.extend({
|
||||
commit_value: function() {
|
||||
var view = this.get_active_view();
|
||||
if (view && view.type === "list" && view.controller.__focus) {
|
||||
var def = $.Deferred();
|
||||
view.controller._on_blur_one2many().always(function () {
|
||||
def.resolve();
|
||||
});
|
||||
return def;
|
||||
return $.when(this.mutex.def, view.controller._on_blur_one2many());
|
||||
}
|
||||
return $.when(false);
|
||||
return this.mutex.def;
|
||||
},
|
||||
is_syntax_valid: function() {
|
||||
var view = this.get_active_view();
|
||||
@@ -971,6 +972,8 @@ var X2ManyListView = ListView.extend({
|
||||
var valid = _.every(cached_records, function(record){
|
||||
_.each(fields, function(field){
|
||||
var value = record.values[field.name];
|
||||
field._inhibit_on_change_flag = true;
|
||||
field.no_rerender = true;
|
||||
field.set_value(_.isArray(value) && _.isArray(value[0]) ? [COMMANDS.delete_all()].concat(value) : value);
|
||||
});
|
||||
return _.every(fields, function(field){
|
||||
@@ -1269,7 +1272,7 @@ var One2ManyFormView = FormView.extend({
|
||||
});
|
||||
|
||||
var FieldOne2Many = FieldX2Many.extend({
|
||||
init: function() {
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.x2many_views = {
|
||||
form: One2ManyFormView,
|
||||
@@ -1281,12 +1284,15 @@ var FieldOne2Many = FieldX2Many.extend({
|
||||
this.$el.addClass('oe_form_field_one2many');
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
before_save: function() {
|
||||
if(this.viewmanager.active_view.type === "list"
|
||||
&& this.viewmanager.active_view.controller.editable()) {
|
||||
return this.viewmanager.active_view.controller.save_edition();
|
||||
commit_value: function() {
|
||||
var self = this;
|
||||
var view = this.viewmanager.active_view;
|
||||
if(view.type === "list" && view.controller.editable()) {
|
||||
return this.mutex.def.then(function () {
|
||||
return view.controller.save_edition();
|
||||
});
|
||||
}
|
||||
return $.when();
|
||||
return this.mutex.def;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1388,7 +1394,6 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
|
||||
this._super(field_manager, node);
|
||||
common.CompletionFieldMixin.init.call(this);
|
||||
this.set({"value": []});
|
||||
this._display_orderer = new utils.DropMisordered();
|
||||
|
||||
var self = this;
|
||||
// We need to know if the field 'color' exists on the model
|
||||
@@ -1398,6 +1403,10 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
|
||||
});
|
||||
});
|
||||
},
|
||||
commit_value: function() {
|
||||
this.dataset.cancel_read();
|
||||
return this._super();
|
||||
},
|
||||
initialize_content: function() {
|
||||
if(!this.get("effective_readonly")) {
|
||||
this.many2one = new FieldMany2One(this.field_manager, this.node);
|
||||
@@ -1434,10 +1443,9 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
|
||||
},
|
||||
get_render_data: function(ids){
|
||||
var self = this;
|
||||
return this.mutex.exec(function(){
|
||||
var fields = self.fields.color ? ['display_name', 'name', 'color'] : ['display_name', 'name']; // TODO master: remove useless 'name'
|
||||
return self.dataset.read_ids(ids, fields);
|
||||
});
|
||||
this.dataset.cancel_read();
|
||||
var fields = this.fields.color ? ['display_name', 'name', 'color'] : ['display_name', 'name']; // TODO master: remove useless 'name'
|
||||
return this.dataset.read_ids(ids, fields);
|
||||
},
|
||||
render_tag: function(data) {
|
||||
this.$('.badge').remove();
|
||||
@@ -1457,7 +1465,7 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
|
||||
self.render_tag(data);
|
||||
};
|
||||
if (!values || values.length > 0) {
|
||||
return this._display_orderer.add(self.get_render_data(values)).done(handle_names);
|
||||
return self.get_render_data(values).done(handle_names);
|
||||
} else {
|
||||
handle_names([]);
|
||||
}
|
||||
|
||||
@@ -584,9 +584,8 @@ var FormView = View.extend(common.FieldManagerMixin, {
|
||||
field.node.attrs.domain = domain;
|
||||
});
|
||||
|
||||
if (!_.isEmpty(result.value)) {
|
||||
this._internal_set_values(result.value);
|
||||
}
|
||||
var def = $.when(!_.isEmpty(result.value) && this._internal_set_values(result.value));
|
||||
|
||||
// FIXME XXX a list of warnings?
|
||||
if (!_.isEmpty(result.warning)) {
|
||||
this.warning_displayed = true;
|
||||
@@ -601,7 +600,7 @@ var FormView = View.extend(common.FieldManagerMixin, {
|
||||
});
|
||||
}
|
||||
|
||||
return $.Deferred().resolve();
|
||||
return def;
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
crash_manager.show_message(e);
|
||||
@@ -611,18 +610,18 @@ var FormView = View.extend(common.FieldManagerMixin, {
|
||||
_process_operations: function() {
|
||||
var self = this;
|
||||
return this.mutating_mutex.exec(function() {
|
||||
function onchanges_mutex () {return self.onchanges_mutex.def;}
|
||||
function iterate() {
|
||||
|
||||
var mutex = new utils.Mutex();
|
||||
mutex.exec(onchanges_mutex);
|
||||
_.each(self.fields, function(field) {
|
||||
self.onchanges_mutex.def.then(function(){
|
||||
mutex.exec(function(){
|
||||
return field.commit_value();
|
||||
});
|
||||
mutex.exec(function(){
|
||||
return field.commit_value();
|
||||
});
|
||||
mutex.exec(onchanges_mutex);
|
||||
});
|
||||
|
||||
return mutex.def.then(function () { return self.onchanges_mutex.def; }).then(function() {
|
||||
return mutex.def.then(function() {
|
||||
var save_obj = self.save_list.pop();
|
||||
if (save_obj) {
|
||||
return self._process_save(save_obj).then(function() {
|
||||
@@ -863,19 +862,6 @@ var FormView = View.extend(common.FieldManagerMixin, {
|
||||
readonly_values = {},
|
||||
deferred = [];
|
||||
|
||||
_.each(self.fields, function (f) {
|
||||
var res = f.before_save();
|
||||
if (res) {
|
||||
deferred.push(res);
|
||||
res.fail(function () {
|
||||
form_invalid = true;
|
||||
if (!first_invalid_field) {
|
||||
first_invalid_field = f;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$.when.apply($, deferred).always(function () {
|
||||
|
||||
_.each(self.fields, function (f) {
|
||||
|
||||
@@ -155,7 +155,7 @@ var FieldTextHtmlSimple = widget.extend({
|
||||
is_false: function() {
|
||||
return !this.get('value') || this.get('value') === "<p><br/></p>" || !this.get('value').match(/\S/);
|
||||
},
|
||||
before_save: function() {
|
||||
commit_value: function() {
|
||||
if (this.options['style-inline']) {
|
||||
transcoder.class_to_style(this.$content);
|
||||
transcoder.font_to_img(this.$content);
|
||||
@@ -361,7 +361,7 @@ var FieldTextHtml = widget.extend({
|
||||
is_false: function() {
|
||||
return this.get('value') === false || !this.$content.html() || !this.$content.html().match(/\S/);
|
||||
},
|
||||
before_save: function () {
|
||||
commit_value: function () {
|
||||
if (this.lang !== 'en_US' && this.$body.find('.o_dirty').length) {
|
||||
this.internal_set_value( this.view.datarecord[this.name] );
|
||||
this._dirty_flag = false;
|
||||
|
||||
Reference in New Issue
Block a user