summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/basic/basic_model.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/views/basic/basic_model.js')
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js74
1 files changed, 49 insertions, 25 deletions
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 1df118ecfd9..4412d29c455 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -1092,9 +1092,12 @@ var BasicModel = AbstractModel.extend({
* @param {boolean} [options.doNotSetDirty=false] if this flag is set to
* true, then we will not tag the record as dirty. This should be avoided
* for most situations.
+ * @param {boolean} [options.notifyChange=true] if this flag is set to
+ * false, then we will not notify and not trigger the onchange, even though
+ * it was changed.
* @param {string} [options.viewType] current viewType. If not set, we will assume
* main viewType from the record
- * @returns {Deferred}
+ * @returns {Deferred} list of changed fields
*/
_applyChange: function (recordID, changes, options) {
var self = this;
@@ -1106,6 +1109,10 @@ var BasicModel = AbstractModel.extend({
if (!options.doNotSetDirty) {
record._isDirty = true;
}
+ var initialData = {};
+ this._visitChildren(record, function (elem) {
+ initialData[elem.id] = $.extend(true, {}, _.pick(elem, 'data', '_changes'));
+ });
// apply changes to local data
for (var fieldName in changes) {
@@ -1119,6 +1126,10 @@ var BasicModel = AbstractModel.extend({
}
}
+ if (options.notifyChange === false) {
+ return $.Deferred().resolve(_.keys(changes));
+ }
+
return $.when.apply($, defs).then(function () {
var onChangeFields = []; // the fields that have changed and that have an on_change
for (var fieldName in changes) {
@@ -1130,12 +1141,18 @@ var BasicModel = AbstractModel.extend({
}
}
}
- var onchangeDef;
+ var onchangeDef = $.Deferred();
if (onChangeFields.length) {
- onchangeDef = self._performOnChange(record, onChangeFields, options.viewType).then(function (result) {
- delete record._warning;
- return _.keys(changes).concat(Object.keys(result && result.value || {}));
- });
+ self._performOnChange(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]);
+ });
+ onchangeDef.resolve({});
+ });
} else {
onchangeDef = $.Deferred().resolve(_.keys(changes));
}
@@ -1306,15 +1323,17 @@ var BasicModel = AbstractModel.extend({
} else {
var fieldInfo = record.fieldsInfo[viewType][name];
if (!fieldInfo) {
- return; //ignore changes of x2many not in view
+ return; // ignore changes of x2many not in view
}
+ var view = fieldInfo.views && fieldInfo.views[fieldInfo.mode];
list = self._makeDataPoint({
- fieldsInfo: fieldInfo.fieldsInfo,
+ fields: view ? view.fields : fieldInfo.relatedFields,
+ fieldsInfo: view ? view.fieldsInfo : fieldInfo.fieldsInfo,
modelName: field.relation,
parentID: record.id,
static: true,
type: 'list',
- viewType: fieldInfo.viewType,
+ viewType: view ? view.type : fieldInfo.viewType,
});
}
// TODO: before registering the changes, verify that the x2many
@@ -2305,6 +2324,7 @@ var BasicModel = AbstractModel.extend({
var ids = record.data[fieldName] || [];
var list = self._makeDataPoint({
count: ids.length,
+ context: record.context,
fieldsInfo: fieldsInfo,
fields: view ? view.fields : fieldInfo.relatedFields,
limit: fieldInfo.limit,
@@ -2643,13 +2663,21 @@ var BasicModel = AbstractModel.extend({
}
commands[fieldName].push(command);
} else if (_.contains(addedIds, list.res_ids[i])) {
- // this is a new id
+ // this is a new id (maybe existing in DB, but new in JS)
relRecord = _.findWhere(relRecordAdded, {res_id: list.res_ids[i]});
changes = this._generateChanges(relRecord, options);
if ('id' in changes) {
+ // the subrecord already exists in db
delete changes.id;
- commands[fieldName].push(x2ManyCommands.update(relRecord.res_id, changes));
+ if (this.isNew(record.id)) {
+ // if the main record is new, link the subrecord to it
+ commands[fieldName].push(x2ManyCommands.link_to(relRecord.res_id));
+ }
+ if (!_.isEmpty(changes)) {
+ commands[fieldName].push(x2ManyCommands.update(relRecord.res_id, changes));
+ }
} else {
+ // the subrecord is new, so create it
commands[fieldName].push(x2ManyCommands.create(relRecord.ref, changes));
}
}
@@ -2882,7 +2910,8 @@ var BasicModel = AbstractModel.extend({
* @returns {boolean}
*/
_isFieldProtected: function (record, fieldName, viewType) {
- var fieldInfo = record.fieldsInfo[viewType || record.viewType][fieldName];
+ var fieldInfo = record.fieldsInfo &&
+ (record.fieldsInfo[viewType || record.viewType][fieldName]);
if (fieldInfo) {
var rawModifiers = fieldInfo.modifiers || {};
var modifiers = this._evalModifiers(record, rawModifiers);
@@ -3239,15 +3268,18 @@ var BasicModel = AbstractModel.extend({
});
return $.when.apply($, defs)
.then(function () {
- return self._performOnChange(record, fields_key).then(function () {
+ var def = $.Deferred();
+ self._performOnChange(record, fields_key).always(function () {
if (record._warning) {
if (params.allowWarning) {
delete record._warning;
} else {
- return $.Deferred().reject();
+ def.reject();
}
}
+ def.resolve();
});
+ return def;
})
.then(function () {
return self._fetchRelationalData(record);
@@ -3314,10 +3346,7 @@ var BasicModel = AbstractModel.extend({
* @param {string[]} fields changed fields
* @param {string} [viewType] current viewType. If not set, we will assume
* main viewType from the record
- * @returns {Deferred} Note: this deferred cannot fail. It is either in the
- * 'success' or 'pending' state. If the onchange rpc fails, it will be
- * resolved with an empty dictionary. Note that the initial change was
- * already applied.
+ * @returns {Deferred}
*/
_performOnChange: function (record, fields, viewType) {
var self = this;
@@ -3337,9 +3366,7 @@ var BasicModel = AbstractModel.extend({
var context = this._getContext(record, options);
var currentData = this._generateOnChangeData(record, {changesOnly: false});
- var def = $.Deferred();
-
- self._rpc({
+ return self._rpc({
model: record.model,
method: 'onchange',
args: [idList, currentData, fields, onchangeSpec, context],
@@ -3364,12 +3391,9 @@ var BasicModel = AbstractModel.extend({
record._domains = _.extend(record._domains, result.domain);
}
return self._applyOnChange(result.value, record).then(function () {
- def.resolve(result);
+ return result;
});
- }).fail(function () {
- def.resolve({});
});
- return def;
},
/**
* Once a record is created and some data has been fetched, we need to do