[IMP] web_widget_one2many_product_picker: Add option to ignore onchange warnings

pull/1858/head
Alexandre D. Díaz 2021-02-19 23:56:00 +01:00
parent 8d91637ed9
commit 78fdd8580c
12 changed files with 81 additions and 173 deletions

View File

@ -86,6 +86,8 @@ Widget options:
will lose part of its functionality as the document will be saved every time you will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget. modify/create a record with the widget.
* ignore_warning > Enable/Disable display onchange warnings (False by default)
All widget options are optional. All widget options are optional.
Notice that you can call '_' method to use translations. This only can be used with this widget. Notice that you can call '_' method to use translations. This only can be used with this widget.

View File

@ -4,7 +4,7 @@
{ {
'name': 'Web Widget One2Many Product Picker', 'name': 'Web Widget One2Many Product Picker',
'summary': 'Widget to select products on one2many fields', 'summary': 'Widget to select products on one2many fields',
'version': '12.0.2.2.0', 'version': '12.0.2.3.0',
'category': 'Website', 'category': 'Website',
'author': "Tecnativa, " 'author': "Tecnativa, "
"Odoo Community Association (OCA)", "Odoo Community Association (OCA)",

View File

@ -25,7 +25,7 @@ msgstr "Afegir"
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192 #: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format #, python-format
msgid "All" msgid "All"
msgstr "Tot" msgstr "Tot"
@ -114,7 +114,7 @@ msgstr "Imatge variant mitjana ( calculada)"
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340 #: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format #, python-format
msgid "[No widget %s]" msgid "[No widget %s]"
msgstr "[Sense widget %s]" msgstr "[Sense widget %s]"

View File

@ -25,7 +25,7 @@ msgstr "Añadir"
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192 #: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format #, python-format
msgid "All" msgid "All"
msgstr "Todo" msgstr "Todo"
@ -114,7 +114,7 @@ msgstr "Imagen variante media (calculada)"
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340 #: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format #, python-format
msgid "[No widget %s]" msgid "[No widget %s]"
msgstr "[Sin widget %s]" msgstr "[Sin widget %s]"

View File

@ -23,7 +23,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192 #: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format #, python-format
msgid "All" msgid "All"
msgstr "" msgstr ""
@ -84,12 +84,16 @@ msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#: model:ir.model.fields,help:web_widget_one2many_product_picker.field_product_product__image_variant_medium #: model:ir.model.fields,help:web_widget_one2many_product_picker.field_product_product__image_variant_medium
msgid "This field holds the image used as image for the product variantor product image medium, limited to 512x512px." msgid ""
"This field holds the image used as image for the product variantor product "
"image medium, limited to 512x512px."
msgstr "" msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#: model:ir.model.fields,help:web_widget_one2many_product_picker.field_product_product__image_variant_big #: model:ir.model.fields,help:web_widget_one2many_product_picker.field_product_product__image_variant_big
msgid "This field holds the image used as image for the product variantor product image, limited to 1024x1024px." msgid ""
"This field holds the image used as image for the product variantor product "
"image, limited to 1024x1024px."
msgstr "" msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
@ -104,7 +108,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340 #: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format #, python-format
msgid "[No widget %s]" msgid "[No widget %s]"
msgstr "" msgstr ""

View File

@ -22,7 +22,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192 #: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format #, python-format
msgid "All" msgid "All"
msgstr "" msgstr ""
@ -103,7 +103,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker #. module: web_widget_one2many_product_picker
#. openerp-web #. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340 #: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format #, python-format
msgid "[No widget %s]" msgid "[No widget %s]"
msgstr "" msgstr ""

View File

@ -44,6 +44,8 @@ Widget options:
will lose part of its functionality as the document will be saved every time you will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget. modify/create a record with the widget.
* ignore_warning > Enable/Disable display onchange warnings (False by default)
All widget options are optional. All widget options are optional.
Notice that you can call '_' method to use translations. This only can be used with this widget. Notice that you can call '_' method to use translations. This only can be used with this widget.

View File

@ -471,6 +471,8 @@ You need to define the view fields. The view must be of <tt class="docutils lite
will lose part of its functionality as the document will be saved every time you will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget.</p> modify/create a record with the widget.</p>
</li> </li>
<li><p class="first">ignore_warning &gt; Enable/Disable display onchange warnings (False by default)</p>
</li>
</ul> </ul>
<p>All widget options are optional. <p>All widget options are optional.
Notice that you can call _ method to use translations. This only can be used with this widget.</p> Notice that you can call _ method to use translations. This only can be used with this widget.</p>

View File

@ -557,6 +557,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_addProduct: function () { _addProduct: function () {
var self = this; var self = this;
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
var record = model.get(this.state.id); var record = model.get(this.state.id);
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty); var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
if (changes[this.options.fieldMap.product_uom_qty] === 0) { if (changes[this.options.fieldMap.product_uom_qty] === 0) {
@ -564,7 +565,10 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
} }
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
this.$card.addClass("blocked"); this.$card.addClass("blocked");
return model.notifyChanges(record.id, changes).then(function () { return model.notifyChanges(
record.id,
changes
).then(function () {
self._saveRecord(); self._saveRecord();
}); });
}, },
@ -577,11 +581,15 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_incProductQty: function (amount) { _incProductQty: function (amount) {
var self = this; var self = this;
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
var record = model.get(this.state.id); var record = model.get(this.state.id);
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty); var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
changes[this.options.fieldMap.product_uom_qty] += amount; changes[this.options.fieldMap.product_uom_qty] += amount;
return model.notifyChanges(record.id, changes).then(function () { return model.notifyChanges(
record.id,
changes
).then(function () {
self._processDynamicFields(); self._processDynamicFields();
self._lazyUpdateRecord(); self._lazyUpdateRecord();
}); });

View File

@ -300,6 +300,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
}); });
this.$extraButtonsContainer = $(qweb.render("One2ManyProductPicker.ExtraButtons")); this.$extraButtonsContainer = $(qweb.render("One2ManyProductPicker.ExtraButtons"));
this.$btnLoadMore = this.$extraButtonsContainer.find("#productPickerLoadMore"); this.$btnLoadMore = this.$extraButtonsContainer.find("#productPickerLoadMore");
this.search_data = this._sort_search_data(this.search_data);
return $.Deferred(function (d) { return $.Deferred(function (d) {
var defs = self.appendSearchRecords(self.search_data, true); var defs = self.appendSearchRecords(self.search_data, true);
defs[0].then(function () { defs[0].then(function () {
@ -316,6 +317,31 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
}); });
}, },
/**
* @param {Array} datas
* @returns {Array}
*/
_sort_search_data: function (datas) {
if (this.search_group.name === "main_lines") {
var field_name = this.options.field_map.product;
for (var index_datas in datas) {
var data = datas[index_datas];
for (var index_state in this.state.data) {
var state_data = this.state.data[index_state];
if (state_data.data[field_name].res_id === data.id) {
data._order_value = state_data.res_id;
}
}
}
var sorted_datas = _.chain(datas).sortBy('_order_value').map(function(item) {
return _.omit(item, '_order_value');
}).value().reverse();
return sorted_datas;
}
return datas;
},
/** /**
* Compare search results with current lines. * Compare search results with current lines.
* Link a current state with the 'search record'. * Link a current state with the 'search record'.
@ -385,6 +411,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
editDiscount: this.options.edit_discount, editDiscount: this.options.edit_discount,
editPrice: this.options.edit_price, editPrice: this.options.edit_price,
autoSave: this.options.auto_save, autoSave: this.options.auto_save,
ignoreWarning: this.options.ignore_warning,
}); });
}, },

View File

@ -79,8 +79,9 @@ odoo.define("web_widget_one2many_product_picker.BasicModel", function (require)
self._makeDefaultRecord(list.model, params) self._makeDefaultRecord(list.model, params)
.then(function (recordID) { .then(function (recordID) {
self.setPureVirtual(recordID, true); self.setPureVirtual(recordID, true);
self.updateRecordContext(recordID, {ignore_warning: true});
if (options.data) { if (options.data) {
self._applyChangeNoWarnings( self._applyChange(
recordID, recordID,
options.data, options.data,
params params
@ -95,165 +96,26 @@ odoo.define("web_widget_one2many_product_picker.BasicModel", function (require)
}, },
/** /**
* Cloned '_applyChange' but without warning messages * Adds support to avoid show onchange warnings.
* The implementation is a pure hack that clone
* the context and do a monkey path the
* 'trigger_up' method.
* *
* @private * @override
* @param {Number} recordID
* @param {Object} changes
* @param {Object} options
* @returns {Deferred}
*/ */
_applyChangeNoWarnings: function (recordID, changes, options) { _performOnChange: function (record, fields, viewType) {
var self = this; if (record.context && record.context.ignore_warning) {
var record = this.localData[recordID]; var this_mp = _.clone(this);
var field; var super_call = this.trigger_up;
var defs = []; this_mp.trigger_up = function (event_name, data) {
options = options || {}; if (event_name === 'warning' && data.type === "dialog") {
record._changes = record._changes || {}; return; // Do nothing
if (!options.doNotSetDirty) {
record._isDirty = true;
} }
var initialData = {}; return super_call.apply(this, arguments);
this._visitChildren(record, function (elem) { }.bind(this);
initialData[elem.id] = $.extend(true, {}, _.pick(elem, 'data', '_changes')); return this._super.apply(this_mp, arguments);
});
// Apply changes to local data
for (var fieldName in changes) {
field = record.fields[fieldName];
if (field && (field.type === 'one2many' || field.type === 'many2many')) {
defs.push(this._applyX2ManyChange(
record,
fieldName,
changes[fieldName],
options.viewType,
options.allowWarning));
} else if (field && (field.type === 'many2one' || field.type === 'reference')) {
defs.push(this._applyX2OneChange(record, fieldName, changes[fieldName]));
} else {
record._changes[fieldName] = changes[fieldName];
} }
} return this._super.apply(this, arguments);
if (options.notifyChange === false) {
return $.Deferred().resolve(_.keys(changes));
}
return $.when.apply($, defs).then(function () {
// The fields that have changed and that have an on_change
var onChangeFields = [];
for (var fieldName in changes) {
field = record.fields[fieldName];
if (field && field.onChange) {
var isX2Many = (
field.type === 'one2many' ||
field.type === 'many2many'
);
if (
!isX2Many ||
(
self._isX2ManyValid(
record._changes[fieldName] ||
record.data[fieldName]
)
)
) {
onChangeFields.push(fieldName);
}
}
}
var onchangeDef = $.Deferred();
if (onChangeFields.length) {
self._performOnChangeNoWarnings(record, onChangeFields, options.viewType)
.then(function (result) {
delete record._warning;
onchangeDef.resolve(
_.keys(changes).concat(
Object.keys((result && result.value) || {})));
}).fail(function () {
self._visitChildren(record, function (elem) {
_.extend(elem, initialData[elem.id]);
});
// Safe fix for stable version, for opw-2267444
if (!options.force_fail) {
onchangeDef.resolve({});
} else {
onchangeDef.reject({});
}
});
} else {
onchangeDef = $.Deferred().resolve(_.keys(changes));
}
return onchangeDef.then(function (fieldNames) {
_.each(fieldNames, function (name) {
if (
record._changes &&
record._changes[name] === record.data[name]
) {
delete record._changes[name];
record._isDirty = !_.isEmpty(record._changes);
}
});
return self._fetchSpecialData(record).then(function (fieldNames2) {
// Return the names of the fields that changed (onchange or
// associated special data change)
return _.union(fieldNames, fieldNames2);
});
});
});
},
/**
* Cloned '_performOnChange' but without warning messages
*
* @private
* @param {Object} record
* @param {Object} fields
* @param {String} viewType
* @returns {Deferred}
*/
_performOnChangeNoWarnings: function (record, fields, viewType) {
var self = this;
var onchangeSpec = this._buildOnchangeSpecs(record, viewType);
if (!onchangeSpec) {
return $.when();
}
var idList = record.data.id ? [record.data.id] : [];
var options = {
full: true,
};
if (fields.length === 1) {
fields = fields[0];
// If only one field changed, add its context to the RPC context
options.fieldName = fields;
}
var context = this._getContext(record, options);
var currentData = this._generateOnChangeData(record, {changesOnly: false});
return self._rpc({
model: record.model,
method: 'onchange',
args: [idList, currentData, fields, onchangeSpec, context],
}).then(function (result) {
if (!record._changes) {
// If the _changes key does not exist anymore, it means that
// it was removed by discarding the changes after the rpc
// to onchange. So, in that case, the proper response is to
// ignore the onchange.
return;
}
if (result.domain) {
record._domains = _.extend(record._domains, result.domain);
}
return self._applyOnChange(result.value, record).then(function () {
return result;
});
});
}, },
}); });

View File

@ -439,7 +439,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
discount: "discount", discount: "discount",
}, },
auto_save: false, auto_save: false,
allow_warning: true, ignore_warning: false,
}; };
}, },
@ -662,7 +662,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
}); });
// This will trigger an "state" update // This will trigger an "state" update
this._setValue( this._setValue(
{operation: "UPDATE", id: evt.data.id, data: evt.data.data} {operation: "UPDATE", id: evt.data.id, data: evt.data.data},
).then(function () { ).then(function () {
if (evt.data.callback) { if (evt.data.callback) {
evt.data.callback(); evt.data.callback();
@ -746,7 +746,8 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
* *
* @override * @override
*/ */
_setValue: function () {
_setValue: function (value, options) {
var self = this; var self = this;
return this._super.apply(this, arguments).then(function () { return this._super.apply(this, arguments).then(function () {
self.updateBadgeLines(); self.updateBadgeLines();