summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-02-09 16:13:08 +0100
committerChristophe Simonis <chs@odoo.com>2018-02-09 16:13:08 +0100
commit5f3301e5cbbb2c6e7bff732761eef80e8dd5a33d (patch)
tree48ab6bd9bbda92dea713c0c52bca3396ef939d82 /addons/web
parent715e602bf04ae5a0c9704c599f2145b2808b31b7 (diff)
parent20e4cd5bcd1816a478aedd441efa90a34cf63334 (diff)
[MERGE] forward port branch 11.0 up to 20e4cd5bcd1
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/static/src/js/views/basic/basic_controller.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js51
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_model.js1
-rw-r--r--addons/web/static/tests/views/form_tests.js5
-rw-r--r--addons/web/static/tests/views/list_tests.js33
-rw-r--r--addons/web/static/tests/views/pivot_tests.js29
6 files changed, 97 insertions, 24 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js
index 1c8060a6fe1..432d810bbbb 100644
--- a/addons/web/static/src/js/views/basic/basic_controller.js
+++ b/addons/web/static/src/js/views/basic/basic_controller.js
@@ -511,7 +511,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
// TODO this will tell the renderer to rerender the widget that
// asked for the discard but will unfortunately lose the click
// made on another row if any
- self._confirmChange(self.handle, [ev.data.fieldName], ev)
+ self._confirmChange(recordID, [ev.data.fieldName], ev)
.always(ev.data.onSuccess);
})
.fail(ev.data.onFailure);
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js
index 042d85d414a..58a5cb7a70e 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -254,7 +254,10 @@ var BasicRenderer = AbstractRenderer.extend({
if ('readonly' in modifiers && element.widget) {
var mode = modifiers.readonly ? 'readonly' : modifiersData.baseMode;
if (mode !== element.widget.mode) {
- self._rerenderFieldWidget(element.widget, record, mode);
+ self._rerenderFieldWidget(element.widget, record, {
+ keepBaseMode: true,
+ mode: mode,
+ });
return; // Rerendering already applied the modifiers, no need to go further
}
}
@@ -406,12 +409,25 @@ var BasicRenderer = AbstractRenderer.extend({
* @param {Object} record
* @param {jQuery|AbstractField} [element]
* @param {Object} [options]
- * @param {Object} [options.callback] - the callback to call on registration
- * and on modifiers updates
+ * @param {Object} [options.callback] the callback to call on registration
+ * and on modifiers updates
+ * @param {boolean} [options.keepBaseMode=false] this function registers the
+ * 'baseMode' of the node; this is a field widget specific settings which
+ * represents the generic mode of the widget, regardless of its modifiers
+ * (the interesting case is the list view: all widgets are supposed to be
+ * in the baseMode 'readonly', except the ones that are in the line that
+ * is currently being edited).
+ * With option 'keepBaseMode' set to true, the current baseMode of the
+ * node isn't overridden (this is particularily useful when a field widget
+ * is re-rendered because its readonly modifier changed, as in this case,
+ * we don't want to change its base mode).
+ * @param {string} [options.mode] the 'baseMode' of the node is set to this
+ * value (if not given, it is set to this.mode, the mode of the renderer)
* @returns {Object} for code efficiency, returns the last evaluated
- * modifiers for the given node and record.
+ * modifiers for the given node and record.
*/
_registerModifiers: function (node, record, element, options) {
+ options = options || {};
// Check if we already registered the modifiers for the given node
// If yes, this is simply an update of the related element
// If not, check the modifiers to see if it needs registration
@@ -428,12 +444,11 @@ var BasicRenderer = AbstractRenderer.extend({
this.allModifiersData.push(modifiersData);
}
}
- // we register here the base mode of the node. This is a field widget
- // specific settings which represents the generic mode for the widget,
- // regardless of its modifiers. The interesting case is the list view:
- // all widgets are supposed to be in the baseMode 'readonly', except the
- // ones that are in the line that is currently being edited.
- modifiersData.baseMode = (options && options.mode) || this.mode;
+
+ // Compute node's base mode if necessary
+ if (!options.keepBaseMode) {
+ modifiersData.baseMode = options.mode || this.mode;
+ }
// Evaluate if necessary
if (!modifiersData.evaluatedModifiers[record.id]) {
@@ -497,13 +512,16 @@ var BasicRenderer = AbstractRenderer.extend({
* @private
* @param {Object} node
* @param {Object} record
- * @param {Object} [options]
+ * @param {Object} [options] passed to @_registerModifiers
+ * @param {string} [options.mode] either 'edit' or 'readonly' (defaults to
+ * this.mode, the mode of the renderer)
* @returns {jQueryElement}
*/
_renderFieldWidget: function (node, record, options) {
+ options = options || {};
var fieldName = node.attrs.name;
// Register the node-associated modifiers
- var mode = options && options.mode || this.mode;
+ var mode = options.mode || this.mode;
var modifiers = this._registerModifiers(node, record, null, options);
// Initialize and register the widget
// Readonly status is known as the modifiers have just been registered
@@ -545,7 +563,8 @@ var BasicRenderer = AbstractRenderer.extend({
&& !element.widget.isSet()
));
},
- mode: mode
+ keepBaseMode: !!options.keepBaseMode,
+ mode: mode,
});
self._postProcessField(widget, node);
});
@@ -614,11 +633,11 @@ var BasicRenderer = AbstractRenderer.extend({
* @private
* @param {Widget} widget
* @param {Object} record
- * @param {string} mode either 'readonly' or 'edit'
+ * @param {Object} [options] options passed to @_renderFieldWidget
*/
- _rerenderFieldWidget: function (widget, record, mode) {
+ _rerenderFieldWidget: function (widget, record, options) {
// Render the new field widget
- var $el = this._renderFieldWidget(widget.__node, record, {mode: mode});
+ var $el = this._renderFieldWidget(widget.__node, record, options);
widget.$el.replaceWith($el);
// Destroy the old widget and position the new one at the old one's
diff --git a/addons/web/static/src/js/views/pivot/pivot_model.js b/addons/web/static/src/js/views/pivot/pivot_model.js
index 7eb2ba4bc6b..99a5e4ee334 100644
--- a/addons/web/static/src/js/views/pivot/pivot_model.js
+++ b/addons/web/static/src/js/views/pivot/pivot_model.js
@@ -545,7 +545,6 @@ var PivotModel = AbstractModel.extend({
var data = Array.prototype.slice.call(arguments);
if (data[0][0].__count === 0) {
self.data.has_data = false;
- return;
}
self._prepareData(data);
});
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index 89c5a3d6a1d..d2ec320c6ea 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -630,7 +630,7 @@ QUnit.module('Views', {
});
QUnit.test('readonly attrs on fields are re-evaluated on field change', function (assert) {
- assert.expect(3);
+ assert.expect(4);
var form = createView({
View: FormView,
@@ -656,6 +656,9 @@ QUnit.module('Views', {
form.$('.o_field_boolean input').click();
assert.strictEqual(form.$('span[name="foo"]').length, 1,
"the foo field widget should have been rerendered to now be readonly again");
+ form.$('.o_field_boolean input').click();
+ assert.strictEqual(form.$('input[name="foo"]').length, 1,
+ "the foo field widget should have been rerendered to now be editable again");
form.destroy();
});
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 4a64e17e881..2fafef26c6f 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -1929,7 +1929,7 @@ QUnit.module('Views', {
});
QUnit.test('readonly attrs on fields are re-evaluated on field change', function (assert) {
- assert.expect(7);
+ assert.expect(9);
var list = createView({
View: ListView,
@@ -1963,9 +1963,14 @@ QUnit.module('Views', {
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 3,
"the foo field widget parent cell should now be readonly again");
- // Reswitch the cell to editable and save the row
list.$('tbody tr:nth(0) td:nth(2) input').click();
- list.$('thead').click();
+ assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]').length, 1,
+ "the foo field widget should have been rerendered as editable again");
+ assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2,
+ "the foo field widget parent cell should not be readonly again");
+
+ // Click outside to leave edition mode
+ list.$el.click();
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2,
"there should be 2 readonly foo cells in readonly mode");
@@ -2773,6 +2778,28 @@ QUnit.module('Views', {
list.destroy();
});
+ QUnit.test('pressing ESC discard the current line changes (with required)', function (assert) {
+ assert.expect(3);
+
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch: '<tree editable="top"><field name="foo" required="1"/></tree>',
+ });
+
+ list.$buttons.find('.o_list_button_add').click();
+
+ list.$('input[name="foo"]').trigger({type: 'keydown', which: $.ui.keyCode.ESCAPE});
+ assert.strictEqual(list.$('tr.o_data_row').length, 4,
+ "should have 4 data row in list");
+ assert.strictEqual(list.$('tr.o_data_row.o_selected_row').length, 0,
+ "no rows should be selected");
+ assert.ok(!list.$buttons.find('.o_list_button_save').is(':visible'),
+ "should not have a visible save button");
+ list.destroy();
+ });
+
QUnit.test('field with password attribute', function (assert) {
assert.expect(2);
diff --git a/addons/web/static/tests/views/pivot_tests.js b/addons/web/static/tests/views/pivot_tests.js
index fe8c4c5b3f9..3e77d7aa8b9 100644
--- a/addons/web/static/tests/views/pivot_tests.js
+++ b/addons/web/static/tests/views/pivot_tests.js
@@ -1,7 +1,6 @@
odoo.define('web.pivot_tests', function (require) {
"use strict";
-var Context = require('web.Context');
var core = require('web.core');
var PivotView = require('web.PivotView');
var testUtils = require('web.test_utils');
@@ -739,7 +738,33 @@ QUnit.module('Views', {
},
});
- $('.o_pivot_download').click();
+ pivot.$buttons.find('.o_pivot_download').click();
+ pivot.destroy();
+ });
+
+ QUnit.test('can download a file without data', function (assert) {
+ assert.expect(1);
+
+ this.data.partner.records = [];
+
+ var pivot = createView({
+ View: PivotView,
+ model: "partner",
+ data: this.data,
+ arch: '<pivot>' +
+ '<field name="date" interval="month" type="col"/>' +
+ '<field name="foo" type="measure"/>' +
+ '</pivot>',
+ session: {
+ get_file: function (args) {
+ assert.strictEqual(args.url, '/web/pivot/export_xls',
+ "should call get_file with correct parameters");
+ args.complete();
+ },
+ },
+ });
+
+ pivot.$buttons.find('.o_pivot_download').click();
pivot.destroy();
});