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.js123
1 files changed, 119 insertions, 4 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 ae9f0611abf..822302630fa 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -183,6 +183,7 @@ var BasicModel = AbstractModel.extend({
fields: list.fields,
fieldsInfo: list.fieldsInfo,
parentID: list.id,
+ position: position,
viewType: list.viewType,
};
return this._makeDefaultRecord(list.model, params).then(function (id) {
@@ -305,6 +306,104 @@ var BasicModel = AbstractModel.extend({
});
},
/**
+ * Compute the default value that the handle field should take.
+ * We need to compute this in order for new lines to be added at the correct position.
+ *
+ * @private
+ * @param {Object} listID
+ * @param {string} position
+ * @return {Object} empty object if no overrie has to be done, or:
+ * field: the name of the field to override,
+ * value: the value to use for that field
+ */
+ _computeOverrideDefaultFields: function (listID, position) {
+ var list = this.localData[listID];
+ var handleField;
+
+ // Here listID is actually just parentID, it's not yet confirmed
+ // to be a list.
+ // If we are not in the case that interests us,
+ // listID will be undefined and this check will work.
+ if (!list) {
+ return {};
+ }
+
+ position = position || 'bottom';
+
+ // Let's find if there is a field with handle.
+ if (!list.fieldsInfo) {
+ return {};
+ }
+ for (var field in list.fieldsInfo.list) {
+ if (list.fieldsInfo.list[field].widget === 'handle') {
+ handleField = field;
+ break;
+ // If there are 2 handle fields on the same list,
+ // we take the first one we find.
+ // And that will be alphabetically on the field name...
+ }
+ }
+
+ if (!handleField) {
+ return {};
+ }
+
+ // We don't want to override the default value
+ // if the list is not ordered by the handle field.
+ var isOrderedByHandle = list.orderedBy
+ && list.orderedBy.length
+ && list.orderedBy[0].asc === true
+ && list.orderedBy[0].name === handleField;
+
+ if (!isOrderedByHandle) {
+ return {};
+ }
+
+ // We compute the list (get) to apply the pending changes before doing our work,
+ // otherwise new lines might not be taken into account.
+ // We use raw: true because we only need to load the first level of relation.
+ var computedList = this.get(list.id, {raw: true});
+
+ // We don't need to worry about the position of a new line if the list is empty.
+ if (!computedList || !computedList.data || !computedList.data.length) {
+ return {};
+ }
+
+ // If there are less elements in the list than the limit of
+ // the page then take the index of the last existing line.
+
+ // If the button is at the top, we want the new element on
+ // the first line of the page.
+
+ // If the button is at the bottom, we want the new element
+ // after the last line of the page
+ // (= theorically it will be the first element of the next page).
+
+ // We ignore list.offset because computedList.data
+ // will only have the current page elements.
+
+ var index = Math.min(
+ computedList.data.length - 1,
+ position !== 'top' ? list.limit - 1 : 0
+ );
+
+ // This positioning will almost be correct. There might just be
+ // an issue if several other lines have the same handleFieldValue.
+
+ // TODO ideally: if there is an element with the same handleFieldValue,
+ // that one and all the following elements must be incremented
+ // by 1 (at least until there is a gap in the numbering).
+
+ // We don't do it now because it's not an important case.
+ var handleFieldValue = computedList.data[index].data[handleField];
+ handleFieldValue = position !== 'top' ? handleFieldValue : handleFieldValue - 1;
+
+ return {
+ field: handleField,
+ value: handleFieldValue,
+ };
+ },
+ /**
* Delete a list of records, then, if the records have a parent, reload it.
*
* @todo we should remove the deleted records from the localData
@@ -1251,15 +1350,16 @@ var BasicModel = AbstractModel.extend({
*/
_addX2ManyDefaultRecord: function (list, options) {
var self = this;
+ var position = options && options.position || 'top';
var params = {
context: this._getContext(list),
fields: list.fields,
fieldsInfo: list.fieldsInfo,
parentID: list.id,
+ position: position,
viewType: list.viewType,
};
return this._makeDefaultRecord(list.model, params).then(function (id) {
- var position = options && options.position || 'top';
list._changes.push({operation: 'ADD', id: id, position: position, isNew: true});
var record = self.localData[id];
list._cache[record.res_id] = id;
@@ -3436,7 +3536,7 @@ var BasicModel = AbstractModel.extend({
_makeDefaultRecord: function (modelName, params) {
var self = this;
- var determineExtraFields = function() {
+ var determineExtraFields = function () {
// Fields that are present in the originating view, that need to be initialized
// Hence preventing their value to crash when getting back to the originating view
var parentRecord = self.localData[params.parentID];
@@ -3446,12 +3546,12 @@ var BasicModel = AbstractModel.extend({
return [];
var fieldsFromOrigin = _.filter(Object.keys(originView[parentRecord.viewType]),
- function(fieldname) {
+ function (fieldname) {
return params.fields[fieldname] !== undefined;
});
return fieldsFromOrigin;
- }
+ };
var fieldNames = Object.keys(params.fieldsInfo[params.viewType]);
var fields_key = _.without(fieldNames, '__last_update');
@@ -3465,6 +3565,7 @@ var BasicModel = AbstractModel.extend({
context: params.context,
})
.then(function (result) {
+
var record = self._makeDataPoint({
modelName: modelName,
fields: params.fields,
@@ -3475,6 +3576,20 @@ var BasicModel = AbstractModel.extend({
viewType: params.viewType,
});
+ // We want to overwrite the default value of the handle field (if any),
+ // in order for new lines to be added at the correct position.
+ // -> This is a rare case where the defaul_get from the server
+ // will be ignored by the view for a certain field (usually "sequence").
+
+ var overrideDefaultFields = self._computeOverrideDefaultFields(
+ params.parentID,
+ params.position
+ );
+
+ if (overrideDefaultFields) {
+ result[overrideDefaultFields.field] = overrideDefaultFields.value;
+ }
+
return self.applyDefaultValues(record.id, result, {fieldNames: _.union(fieldNames, extraFields)})
.then(function () {
var def = $.Deferred();