summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-01-04 14:54:08 +0100
committerChristophe Simonis <chs@odoo.com>2019-01-04 14:54:08 +0100
commitec9400821ecf45d9495740ebcea9e213ef12d3fe (patch)
tree93a7753a321f05fe5fcd88b67e5e29034f5107e7 /addons/web
parent2cdc1cc9ced4364cac403fd0891836dba52bdd08 (diff)
parent27a084eb814acd81679db1e461c53389d6afc875 (diff)
[MERGE] forward port branch saas-11.3 up to 27a084eb814
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js21
-rw-r--r--addons/web/static/src/js/views/basic/basic_view.js15
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_model.js10
-rw-r--r--addons/web/static/src/js/widgets/attach_document.js5
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js93
5 files changed, 133 insertions, 11 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 c9e28db86c6..865cddba657 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -4172,11 +4172,24 @@ var BasicModel = AbstractModel.extend({
}
return def.then(function () {
var resIDs = [];
- // generate the current count and res_ids list by applying the changes
- var currentCount = list.count;
var currentResIDs = list.res_ids;
- var effectiveLimit = (list.limit || 0) - (list.tempLimitIncrement || 0);
- var upperBound = effectiveLimit ? Math.min(list.offset + effectiveLimit, currentCount) : currentCount;
+ // if new records have been added to the list, their virtual ids have
+ // been pushed at the end of res_ids (or at the beginning, depending
+ // on the editable property), ignoring completely the current page
+ // where the records have actually been created ; for that reason,
+ // we use orderedResIDs which is a freezed order with the virtual ids
+ // at the correct position where they were actually inserted ; however,
+ // when we use orderedResIDs, we must filter out ids that are not in
+ // res_ids, which correspond to records that have been removed from
+ // the relation (this information being taken into account in res_ids
+ // but not in orderedResIDs)
+ if (list.orderedResIDs) {
+ currentResIDs = list.orderedResIDs.filter(function (resID) {
+ return list.res_ids.indexOf(resID) >= 0;
+ });
+ }
+ var currentCount = currentResIDs.length;
+ var upperBound = list.limit ? Math.min(list.offset + list.limit, currentCount) : currentCount;
var fieldNames = list.getFieldNames();
for (var i = list.offset; i < upperBound; i++) {
var resId = currentResIDs[i];
diff --git a/addons/web/static/src/js/views/basic/basic_view.js b/addons/web/static/src/js/views/basic/basic_view.js
index eb3efe7001d..55fd73eeb50 100644
--- a/addons/web/static/src/js/views/basic/basic_view.js
+++ b/addons/web/static/src/js/views/basic/basic_view.js
@@ -148,6 +148,21 @@ var BasicView = AbstractView.extend({
if (_.difference(fieldViewTypes, recordViewTypes).length) {
fieldNames.push(name);
}
+
+ if (record.data[name].viewType === 'default') {
+ // Use case: x2many (tags) in x2many list views
+ // When opening the x2many record form view, the
+ // x2many will be reloaded but it may not have
+ // the same fields (ex: tags in list and list in
+ // form) so we need to merge the fieldsInfo to
+ // avoid losing the initial fields (display_name)
+ var defaultFieldInfo = record.data[name].fieldsInfo.default;
+ _.each(fieldViews, function (fieldView) {
+ _.each(fieldView.fieldsInfo, function (x2mFieldInfo) {
+ _.defaults(x2mFieldInfo, defaultFieldInfo);
+ });
+ });
+ }
}
}
// Many2one: context is not the same between the different views
diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js
index 320221f1dd9..7c06a7d818d 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -244,18 +244,18 @@ return AbstractModel.extend({
this.setDate(this.data.target_date.clone().add(-1, this.data.scale));
},
/**
- * @todo: this should not work. it ignores the domain/context
- *
* @override
- * @param {any} _handle ignored
- * @param {Object} params
+ * @param {Object} [params.context]
* @param {Array} [params.domain]
* @returns {Deferred}
*/
- reload: function (_handle, params) {
+ reload: function (handle, params) {
if (params.domain) {
this.data.domain = params.domain;
}
+ if (params.context) {
+ this.data.context = params.context;
+ }
return this._loadCalendar();
},
/**
diff --git a/addons/web/static/src/js/widgets/attach_document.js b/addons/web/static/src/js/widgets/attach_document.js
index 041b021d60b..13496f3aea7 100644
--- a/addons/web/static/src/js/widgets/attach_document.js
+++ b/addons/web/static/src/js/widgets/attach_document.js
@@ -11,7 +11,7 @@ var _t = core._t;
var AttachDocument = Widget.extend({
template: 'AttachDocument',
events: {
- 'click span.o_attach_document': '_onClickAttachDocument',
+ 'click': '_onClickAttachDocument',
'change input.o_input_file': '_onFileChanged',
},
/**
@@ -76,6 +76,9 @@ var AttachDocument = Widget.extend({
* @param {Event} ev
*/
_onClickAttachDocument: function (ev) {
+ if ($(ev.target).is('input.o_input_file')) {
+ return;
+ }
var fieldNames = this.getParent().canBeSaved(this.state.id);
if (fieldNames.length) {
return this._notifyInvalidFields(fieldNames);
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index 9cf7ebba16e..602dc9a0331 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -4072,6 +4072,50 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('delete a record while adding another one in a multipage', function (assert) {
+ // in a many2one with at least 2 pages, add a new line. Delete the line above it.
+ // (the onchange makes it so that the virtualID is inserted in the middle of the currentResIDs.)
+ // it should load the next line to display it on the page.
+ assert.expect(2);
+
+ this.data.partner.records[0].turtles = [2, 3];
+ this.data.partner.onchanges.turtles = function (obj) {
+ obj.turtles = [[5]].concat(obj.turtles);
+ };
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:'<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="turtles">' +
+ '<tree editable="bottom" limit="1" decoration-muted="turtle_bar == False">' +
+ '<field name="turtle_foo"/>' +
+ '<field name="turtle_bar"/>' +
+ '</tree>' +
+ '</field>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+ // add a line (virtual record)
+ form.$('.o_field_x2many_list_row_add a').click();
+ form.$('.o_input').val('pi').trigger('input');
+ // delete the line above it
+ form.$('.o_list_record_remove').first().click();
+ // the next line should be displayed below the newly added one
+ assert.strictEqual(form.$('.o_data_row').length, 2, "should have 2 records");
+ assert.strictEqual(form.$('.o_data_row .o_data_cell:first-child').text(), 'pikawa',
+ "should display the correct records on page 1");
+
+ form.destroy();
+ });
+
QUnit.test('onchange returning a command 6 for an x2many', function (assert) {
assert.expect(2);
@@ -6375,7 +6419,7 @@ QUnit.module('relational_fields', {
'</form>',
res_id: 1,
mockRPC: function (route, args) {
- assert.step(args.method + ' ' + args.model)
+ assert.step(args.method + ' ' + args.model);
return this._super(route, args);
},
viewOptions: {
@@ -12791,6 +12835,53 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('widget many2many_tags in one2many with display_name', function (assert) {
+ assert.expect(4);
+ this.data.turtle.records[0].partner_ids = [2];
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<field name="turtles">' +
+ '<tree>' +
+ '<field name="partner_ids" widget="many2many_tags"/>' + // will use display_name
+ '</tree>' +
+ '<form>' +
+ '<sheet>' +
+ '<field name="partner_ids"/>' +
+ '</sheet>' +
+ '</form>' +
+ '</field>' +
+ '</sheet>' +
+ '</form>',
+ archs: {
+ 'partner,false,list': '<tree><field name="foo"/></tree>',
+ },
+ res_id: 1,
+ });
+
+ assert.strictEqual(form.$('.o_field_one2many[name="turtles"] .o_list_view .o_field_many2manytags[name="partner_ids"]').text().replace(/\s/g, ''),
+ "secondrecordaaa", "the tags should be correctly rendered");
+
+ // open the x2m form view
+ form.$('.o_field_one2many[name="turtles"] .o_list_view td.o_data_cell:first').click();
+ assert.strictEqual($('.modal .o_form_view .o_field_many2many[name="partner_ids"] .o_list_view .o_data_cell').text(),
+ "blipMy little Foo Value", "the list view should be correctly rendered with foo");
+
+ $('.modal button.o_form_button_cancel').click();
+ assert.strictEqual(form.$('.o_field_one2many[name="turtles"] .o_list_view .o_field_many2manytags[name="partner_ids"]').text().replace(/\s/g, ''),
+ "secondrecordaaa", "the tags should still be correctly rendered");
+
+ form.$buttons.find('.o_form_button_edit').click();
+ assert.strictEqual(form.$('.o_field_one2many[name="turtles"] .o_list_view .o_field_many2manytags[name="partner_ids"]').text().replace(/\s/g, ''),
+ "secondrecordaaa", "the tags should still be correctly rendered");
+
+ form.destroy();
+ });
+
QUnit.test('widget many2many_tags: tags title attribute', function (assert) {
assert.expect(1);
this.data.turtle.records[0].partner_ids = [2];