summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/basic/basic_model.js
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-10-09 11:37:30 +0200
committerChristophe Simonis <chs@odoo.com>2018-10-09 11:37:30 +0200
commit835b77ba94bd42cd071c8077ff9a86ce977fddab (patch)
treeb53dfe3553f0cd90681270b0fdd6ae96436bf2ae /addons/web/static/src/js/views/basic/basic_model.js
parentc36dedb0958548d0fe3f83d1d17c223ae26d247a (diff)
parentebe43bad9eff9875e7b75f41aa17b90b1d9912a7 (diff)
[MERGE] forward port branch 12.0 up to ebe43bad9ef
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.js100
1 files changed, 70 insertions, 30 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 fbb4b0b122c..f6bf46aed68 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -134,6 +134,9 @@ var x2ManyCommands = {
};
var BasicModel = AbstractModel.extend({
+ // constants
+ OPEN_GROUP_LIMIT: 10, // after this limit, groups are automatically folded
+
// list of models for which the DataManager's cache should be cleared on
// create, update and delete operations
noCacheModels: [
@@ -594,6 +597,7 @@ var BasicModel = AbstractModel.extend({
getDomain: element.getDomain,
getFieldNames: element.getFieldNames,
id: element.id,
+ isDirty: element.isDirty,
limit: element.limit,
model: element.model,
offset: element.offset,
@@ -648,6 +652,7 @@ var BasicModel = AbstractModel.extend({
getFieldNames: element.getFieldNames,
groupedBy: element.groupedBy,
id: element.id,
+ isDirty: element.isDirty,
isOpen: element.isOpen,
limit: element.limit,
model: element.model,
@@ -1323,34 +1328,54 @@ var BasicModel = AbstractModel.extend({
* @param {Object} [options]
* @param {string} [options.position=top] if the new record should be added
* on top or on bottom of the list
- * @param {Object} [options.context] additional context to be merged before
- * calling the default_get (eg. to set default values)
- * @returns {Deferred<string>} resolves to the new record id
+ * @param {Array} [options.[context]] additional context to be merged before
+ * calling the default_get (eg. to set default values).
+ * If several contexts are found, multiple records are added
+ * @param {boolean} [options.allowWarning=false] if true, the default record
+ * operation can complete, even if a warning is raised
+ * @returns {Deferred<[string]>} resolves to the new records ids
*/
_addX2ManyDefaultRecord: function (list, options) {
var self = this;
var position = options && options.position || 'top';
- var additionalContext = options && options.context;
- var context = this._getContext(list, {additionalContext: additionalContext});
var params = {
- context: context,
fields: list.fields,
fieldsInfo: list.fieldsInfo,
parentID: list.id,
position: position,
viewType: list.viewType,
+ allowWarning: options && options.allowWarning
};
- return this._makeDefaultRecord(list.model, params).then(function (id) {
- list._changes.push({operation: 'ADD', id: id, position: position, isNew: true});
- var record = self.localData[id];
- list._cache[record.res_id] = id;
- if (list.orderedResIDs) {
- var index = list.offset + (position !== 'top' ? list.limit : 0);
- list.orderedResIDs.splice(index, 0, record.res_id);
- // list could be a copy of the original one
- self.localData[list.id].orderedResIDs = list.orderedResIDs;
- }
- return id;
+
+ var additionalContexts = options && options.context;
+ var makeDefaultRecords = [];
+ if (additionalContexts){
+ _.each(additionalContexts, function (context) {
+ params.context = self._getContext(list, {additionalContext: context});
+ makeDefaultRecords.push(self._makeDefaultRecord(list.model, params));
+ });
+ } else {
+ params.context = self._getContext(list);
+ makeDefaultRecords.push(self._makeDefaultRecord(list.model, params));
+ }
+
+ return $.when.apply($, makeDefaultRecords).then(function (){
+ var ids = [];
+ _.each(arguments, function (id){
+ ids.push(id);
+
+ list._changes.push({operation: 'ADD', id: id, position: position, isNew: true});
+ var record = self.localData[id];
+ list._cache[record.res_id] = id;
+ if (list.orderedResIDs) {
+ var index = list.offset + (position !== 'top' ? list.limit : 0);
+ list.orderedResIDs.splice(index, 0, record.res_id);
+ // list could be a copy of the original one
+ self.localData[list.id].orderedResIDs = list.orderedResIDs;
+ }
+ });
+
+ return ids;
});
},
/**
@@ -1369,6 +1394,9 @@ var BasicModel = AbstractModel.extend({
* it was changed.
* @param {string} [options.viewType] current viewType. If not set, we will assume
* main viewType from the record
+ * @param {boolean} [options.allowWarning=false] if true, change
+ * operation can complete, even if a warning is raised
+ * (only supported by X2ManyChange)
* @returns {Deferred} list of changed fields
*/
_applyChange: function (recordID, changes, options) {
@@ -1390,7 +1418,7 @@ var BasicModel = AbstractModel.extend({
for (var fieldName in changes) {
field = record.fields[fieldName];
if (field.type === 'one2many' || field.type === 'many2many') {
- defs.push(this._applyX2ManyChange(record, fieldName, changes[fieldName], options.viewType));
+ defs.push(this._applyX2ManyChange(record, fieldName, changes[fieldName], options.viewType, options.allowWarning));
} else if (field.type === 'many2one' || field.type === 'reference') {
defs.push(this._applyX2OneChange(record, fieldName, changes[fieldName]));
} else {
@@ -1717,9 +1745,12 @@ var BasicModel = AbstractModel.extend({
* key. For example, it looks like {operation: ADD, id: 'partner_1'}
* @param {string} [viewType] current viewType. If not set, we will assume
* main viewType from the record
+ * @param {boolean} [allowWarning=false] if true, change
+ * operation can complete, even if a warning is raised
+ * (only supported by the 'CREATE' command.operation)
* @returns {Deferred}
*/
- _applyX2ManyChange: function (record, fieldName, command, viewType) {
+ _applyX2ManyChange: function (record, fieldName, command, viewType, allowWarning) {
if (command.operation === 'TRIGGER_ONCHANGE') {
// the purpose of this operation is to trigger an onchange RPC, so
// there is no need to apply any change on the record (the changes
@@ -1814,16 +1845,19 @@ var BasicModel = AbstractModel.extend({
var options = {
context: command.context,
position: command.position,
+ allowWarning: allowWarning
};
- def = this._addX2ManyDefaultRecord(list, options).then(function (id) {
- if (command.position === 'bottom' && list.orderedResIDs && list.orderedResIDs.length >= list.limit) {
- list.tempLimitIncrement = (list.tempLimitIncrement || 0) + 1;
- list.limit += 1;
- }
- // FIXME: hack for lunch widget, which does useless default_get and onchange
- if (command.data) {
- return self._applyChange(id, command.data);
- }
+ def = this._addX2ManyDefaultRecord(list, options).then(function (ids) {
+ _.each(ids, function(id){
+ if (command.position === 'bottom' && list.orderedResIDs && list.orderedResIDs.length >= list.limit) {
+ list.tempLimitIncrement = (list.tempLimitIncrement || 0) + 1;
+ list.limit += 1;
+ }
+ // FIXME: hack for lunch widget, which does useless default_get and onchange
+ if (command.data) {
+ return self._applyChange(id, command.data);
+ }
+ });
});
defs.push(def);
break;
@@ -3490,6 +3524,7 @@ var BasicModel = AbstractModel.extend({
dataPoint.getContext = this._getContext.bind(this, dataPoint);
dataPoint.getDomain = this._getDomain.bind(this, dataPoint);
dataPoint.getFieldNames = this._getFieldNames.bind(this, dataPoint);
+ dataPoint.isDirty = this.isDirty.bind(this, dataPoint.id);
this.localData[dataPoint.id] = dataPoint;
@@ -3971,6 +4006,9 @@ var BasicModel = AbstractModel.extend({
var groupByField = list.groupedBy[0];
var rawGroupBy = groupByField.split(':')[0];
var fields = _.uniq(list.getFieldNames().concat(rawGroupBy));
+ var orderedBy = _.filter(list.orderedBy, function(order){
+ return order.name === rawGroupBy || list.fields[order.name].group_operator !== undefined;
+ });
return this._rpc({
model: list.model,
method: 'read_group',
@@ -3978,7 +4016,7 @@ var BasicModel = AbstractModel.extend({
domain: list.domain,
context: list.context,
groupBy: list.groupedBy,
- orderBy: list.orderedBy,
+ orderBy: orderedBy,
lazy: true,
})
.then(function (groups) {
@@ -3988,6 +4026,7 @@ var BasicModel = AbstractModel.extend({
list.data = [];
list.count = 0;
var defs = [];
+ var openGroupCount = 0;
_.each(groups, function (group) {
var aggregateValues = {};
@@ -4043,7 +4082,7 @@ var BasicModel = AbstractModel.extend({
oldGroup.limit = oldGroup.limit + oldGroup.loadMoreOffset;
_.extend(oldGroup, updatedProps);
newGroup = oldGroup;
- } else if (!newGroup.openGroupByDefault) {
+ } else if (!newGroup.openGroupByDefault || openGroupCount >= self.OPEN_GROUP_LIMIT) {
newGroup.isOpen = false;
} else {
newGroup.isOpen = '__fold' in group ? !group.__fold : true;
@@ -4051,6 +4090,7 @@ var BasicModel = AbstractModel.extend({
list.data.push(newGroup.id);
list.count += newGroup.count;
if (newGroup.isOpen && newGroup.count > 0) {
+ openGroupCount++;
defs.push(self._load(newGroup, options));
}
});