summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js6
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js123
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js4
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js7
4 files changed, 128 insertions, 12 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index 83ce59f1eb6..bf2c303a2bb 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -1293,12 +1293,14 @@ var FieldOne2Many = FieldX2Many.extend({
*/
_onAddRecord: function (ev) {
var self = this;
+ var data = ev.data || {};
+
// we don't want interference with the components upstream.
ev.stopPropagation();
if (this.editable) {
if (!this.activeActions.create) {
- if (ev.data.onFail) {
- ev.data.onFail();
+ if (data.onFail) {
+ data.onFail();
}
} else if (!this.creatingRecord) {
this.creatingRecord = true;
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();
diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index 9ec82878e70..26b4f68d303 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -477,7 +477,7 @@ ListRenderer.include({
},
/**
* The renderer needs to support reordering lines. This is only active in
- * edit mode. The hasHandle attribute is used when there is a sequence
+ * edit mode. The handleField attribute is set when there is a sequence
* widget.
*
* @override
@@ -485,7 +485,7 @@ ListRenderer.include({
*/
_renderBody: function () {
var $body = this._super();
- if (this.hasHandle) {
+ if (this.handleField) {
$body.sortable({
axis: 'y',
items: '> tr.o_data_row',
diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index e84d6687cc9..79304309eb6 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -50,8 +50,9 @@ var ListRenderer = BasicRenderer.extend({
*/
init: function (parent, state, params) {
this._super.apply(this, arguments);
- this.hasHandle = false;
- this.handleField = 'sequence';
+ // This attribute lets us know if there is a handle widget on a field,
+ // and on which field it is set.
+ this.handleField = null;
this._processColumns(params.columnInvisibleFields || {});
this.rowDecorations = _.chain(this.arch.attrs)
.pick(function (value, key) {
@@ -181,7 +182,6 @@ var ListRenderer = BasicRenderer.extend({
*/
_processColumns: function (columnInvisibleFields) {
var self = this;
- self.hasHandle = false;
self.handleField = null;
this.columns = _.reject(this.arch.children, function (c) {
var reject = c.attrs.modifiers.column_invisible;
@@ -191,7 +191,6 @@ var ListRenderer = BasicRenderer.extend({
reject = columnInvisibleFields[c.attrs.name];
}
if (!reject && c.attrs.widget === 'handle') {
- self.hasHandle = true;
self.handleField = c.attrs.name;
}
return reject;