summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/web/static/src/js/core/utils.js17
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js5
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js113
3 files changed, 133 insertions, 2 deletions
diff --git a/addons/web/static/src/js/core/utils.js b/addons/web/static/src/js/core/utils.js
index ac9310dce90..acf8ca4d68d 100644
--- a/addons/web/static/src/js/core/utils.js
+++ b/addons/web/static/src/js/core/utils.js
@@ -349,6 +349,23 @@ var utils = {
].join(';');
},
/**
+ * Sort an array in place, keeping the initial order for identical values.
+ *
+ * @param {Array} array
+ * @param {function} iteratee
+ */
+ stableSort: function (array, iteratee) {
+ var stable = array.slice();
+ return array.sort(function stableCompare (a, b) {
+ var order = iteratee(a, b);
+ if (order !== 0) {
+ return order;
+ } else {
+ return stable.indexOf(a) - stable.indexOf(b);
+ }
+ });
+ },
+ /**
* @param {any} array
* @param {any} elem1
* @param {any} elem2
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 8a9fd496b39..78e9216be62 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -89,6 +89,7 @@ var Context = require('web.Context');
var core = require('web.core');
var Domain = require('web.Domain');
var session = require('web.session');
+var utils = require('web.utils');
var _t = core._t;
@@ -3833,7 +3834,7 @@ var BasicModel = AbstractModel.extend({
for (var k = 0; k < list.orderedResIDs.length; k++) {
orderedResIDs[list.orderedResIDs[k]] = k;
}
- list.res_ids.sort(function compareResIdIndexes (resId1, resId2) {
+ utils.stableSort(list.res_ids, function compareResIdIndexes (resId1, resId2) {
if (!(resId1 in orderedResIDs) && !(resId2 in orderedResIDs)) {
return 0;
}
@@ -3878,7 +3879,7 @@ var BasicModel = AbstractModel.extend({
}
return compareRecords(record1ID, record2ID, level + 1);
};
- list.res_ids.sort(compareRecords);
+ utils.stableSort(list.res_ids, compareRecords);
}
this._setDataInRange(list);
},
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index 208f00298d3..853c3bd69d6 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -2518,6 +2518,119 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('onchange with modifiers for embedded one2many on the second page', function (assert) {
+ assert.expect(7);
+
+ var data = this.data;
+ var ids = [];
+ for (var i=10; i<60; i++) {
+ var id = 10 + i;
+ ids.push(id);
+ data.turtle.records.push({
+ id: id,
+ turtle_int: 0,
+ turtle_foo: "#" + id,
+ });
+ }
+ ids.push(1, 2, 3);
+ data.partner.records[0].turtles = ids;
+ data.partner.onchanges = {
+ turtles: function (obj) {
+ // TODO: make this test more 'difficult'
+ // For now, the server only returns UPDATE commands (no LINK TO)
+ // even though it should do it (for performance reasons)
+ // var turtles = obj.turtles.splice(0, 20);
+
+ var turtles = [];
+ turtles.unshift([5]);
+ // create UPDATE commands for each records (this is the server
+ // usual answer for onchange)
+ for (var k in obj.turtles) {
+ var change = obj.turtles[k];
+ var record = _.findWhere(data.turtle.records, {id: change[1]});
+ if (change[0] === 1) {
+ _.extend(record, change[2]);
+ }
+ turtles.push([1, record.id, record]);
+ }
+ obj.turtles = turtles;
+ },
+ };
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: data,
+ arch:'<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="turtles">' +
+ '<tree editable="bottom" default_order="turtle_int" limit="10">' +
+ '<field name="turtle_int" widget="handle"/>' +
+ '<field name="turtle_foo"/>' +
+ '<field name="turtle_qux" attrs="{\'readonly\': [(\'turtle_foo\', \'=\', False)]}"/>' +
+ '</tree>' +
+ '</field>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "#20#21#22#23#24#25#26#27#28#29",
+ "should display the records in order");
+
+ form.$('.o_field_one2many .o_list_view tbody tr:first td:first').click();
+ form.$('.o_field_one2many .o_list_view tbody tr:first input:first').val('blurp').trigger('input');
+
+ // the domain fail if the widget does not use the allready loaded data.
+ form.$buttons.find('.o_form_button_cancel').click();
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "blurp#21#22#23#24#25#26#27#28#29",
+ "should display the records in order with the changes");
+
+ $('.modal .modal-footer button:first').click();
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "#20#21#22#23#24#25#26#27#28#29",
+ "should cancel changes and display the records in order");
+
+ form.$buttons.find('.o_form_button_edit').click();
+
+ // Drag and drop the third line in second position
+ testUtils.dragAndDrop(
+ form.$('.ui-sortable-handle').eq(2),
+ form.$('.o_field_one2many tbody tr').eq(1),
+ {position: 'top'}
+ );
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "#20#30#31#32#33#34#35#36#37#38",
+ "should display the records in order after resequence (display record with turtle_int=0)");
+
+ // Drag and drop the third line in second position
+ testUtils.dragAndDrop(
+ form.$('.ui-sortable-handle').eq(2),
+ form.$('.o_field_one2many tbody tr').eq(1),
+ {position: 'top'}
+ );
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "#20#39#40#41#42#43#44#45#46#47",
+ "should display the records in order after resequence (display record with turtle_int=0)");
+
+ form.$buttons.find('.o_form_button_cancel').click();
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "#20#39#40#41#42#43#44#45#46#47",
+ "should display the records in order after resequence");
+
+ $('.modal .modal-footer button:first').click();
+
+ assert.equal(form.$('.o_field_one2many td[class="o_data_cell"]').text(), "#20#21#22#23#24#25#26#27#28#29",
+ "should cancel changes and display the records in order");
+
+ form.destroy();
+ });
+
QUnit.test('onchange followed by edition on the second page', function (assert) {
assert.expect(20);