From c75680c527844b3b984fa6dfbe04b612528cd9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 5 May 2017 06:50:59 +0200 Subject: [REF] web: optimize basic model (improve perfs for most views) The 'get' method in the basic model is called very often (too often, but that is another issue). For a large list with many columns, it can be quickly be called more than 10k times. In that function, we had to protect our integrity by performing a deep clone with $.extend, so noone else can be allowed to change something in our internal structure. This is good in theory, but not so good in practice, as $.extend is a really expensive operation. Also, we try to have the smallest external API by deleting useless keys. But instead of keeping a blacklist of private keys, it is simpler to have a whitelist of public keys. So, what we do is to explicitely construct the object returned by key, since we know the types of every values involved. This is more explicit, and at the same time, much faster. Also, we propagate the options for elements of type list. This is why I had to change the isFieldSet method. In a benchmark I just ran, loading and rendering a large list (200 rows, 7 columns) went from about 2.7s to 0.7s. We still do way too much work, but at least it is much faster... --- addons/web/static/tests/fields/basic_fields_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index c1fb007b937..72a9e61f3f5 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1141,7 +1141,7 @@ QUnit.module('basic_fields', { "graph of first record should be a barchart"); assert.strictEqual(kanban.$('.o_kanban_record:nth(1) .o_graph_linechart').length, 1, "graph of second record should be a linechart"); - + var evt = document.createEvent("MouseEvents"); //taken ref from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent evt.initMouseEvent("mouseover", true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); $('.discreteBar')[0].dispatchEvent(evt) -- cgit v1.2.3 From c04b840a45edd222c50e74d18e2d02a3dd3175cd Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 5 May 2017 15:21:36 +0200 Subject: [FIX] web: FieldMonetary: don't loose focus after edition ... in x2many editable list views. Field widgets can detect that they are at the origin of a field_changed event, so that they don't re-render themselves when they are being edited. This didn't work for fields inside x2many list views. This wasn't a big problem for most of the fields, because the cursor position was automatically reset after a re-rendering, but it wasn't working for monetary fields that empty their $el before each re-rendering. This rev. fixes the issue by making the field widgets inside x2many list able to detect that they are the origin of a change, and thus removes the now useless code that restore the cursor position. --- .../web/static/tests/fields/basic_fields_tests.js | 65 +++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 72a9e61f3f5..f2334b61f4a 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1144,9 +1144,9 @@ QUnit.module('basic_fields', { var evt = document.createEvent("MouseEvents"); //taken ref from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent evt.initMouseEvent("mouseover", true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); - $('.discreteBar')[0].dispatchEvent(evt) + $('.discreteBar')[0].dispatchEvent(evt); var tooltip = $('.nvtooltip').find('table').find('.key')[0].innerText; - assert.equal(tooltip,graph_key, "graph tooltip should be generated ") + assert.equal(tooltip,graph_key, "graph tooltip should be generated "); $('.nvtooltip').remove(); // force a re-rendering of the first record (to check if the @@ -1736,6 +1736,67 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('should keep the focus when being edited in x2many lists', function (assert) { + assert.expect(6); + + this.data.partner.fields.currency_id.default = 1; + this.data.partner.fields.m2m = { + string: "m2m", type: "many2many", relation: 'partner', default: [[6, false, [2]]], + }; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '
', + archs: { + 'partner,false,list': '' + + '' + + '' + + '', + }, + session: { + currencies: _.indexBy(this.data.currency.records, 'id'), + }, + }); + + // test the monetary field inside the one2many + var $o2m = form.$('.o_field_widget[name=p]'); + $o2m.find('.o_field_x2many_list_row_add a').click(); + $o2m.find('.o_field_widget input').val("22").trigger('input'); + + assert.strictEqual($o2m.find('.o_field_widget input').get(0), document.activeElement, + "the focus should still be on the input"); + assert.strictEqual($o2m.find('.o_field_widget input').val(), "22", + "the value should not have been formatted yet"); + + form.$el.click(); // focusout the input + + assert.strictEqual($o2m.find('.o_field_widget[name=qux]').html(), "$ 22.00", + "the value should have been formatted after losing the focus"); + + // test the monetary field inside the many2many + var $m2m = form.$('.o_field_widget[name=m2m]'); + $m2m.find('.o_data_row td:first').click(); + $m2m.find('.o_field_widget input').val("22").trigger('input'); + + assert.strictEqual($m2m.find('.o_field_widget input').get(0), document.activeElement, + "the focus should still be on the input"); + assert.strictEqual($m2m.find('.o_field_widget input').val(), "22", + "the value should not have been formatted yet"); + + form.$el.click(); // focusout the input + + assert.strictEqual($m2m.find('.o_field_widget[name=qux]').html(), "22.00 €", + "the value should have been formatted after losing the focus"); + + form.destroy(); + }); + QUnit.module('FieldInteger'); QUnit.test('integer field when unset', function (assert) { -- cgit v1.2.3 From c8d77f93e5a857acd22025f4a8d4d42d674479d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Mon, 8 May 2017 10:55:46 +0200 Subject: [FIX] web: display empty input fields properly Before this commit, it was not possible to see the difference between an unset float field (with a 'false' value) and a set field (for ex, with value 0) This was due to the fact that the formatFloat/formatMonetary functions format false values as the number 0, unlike many other formatting functions. --- addons/web/static/tests/fields/basic_fields_tests.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index f2334b61f4a..6e007949ea7 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -415,9 +415,9 @@ QUnit.module('basic_fields', { '', }); - var zeroValues = list.$('td').filter(function () {return $(this).text() === '0.000';}); - assert.strictEqual(zeroValues.length, 2, - 'Unset float values should be rendered as zeros.'); + var zeroValues = list.$('td.o_data_cell').filter(function () {return $(this).text() === '';}); + assert.strictEqual(zeroValues.length, 1, + 'Unset float values should be rendered as empty strings.'); // switch to edit mode var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector)').first(); @@ -441,8 +441,8 @@ QUnit.module('basic_fields', { QUnit.test('do not trigger a field_changed if they have not changed', function (assert) { assert.expect(2); - this.data.partner.records[1].qux = undefined; - this.data.partner.records[1].int_field = undefined; + this.data.partner.records[1].qux = false; + this.data.partner.records[1].int_field = false; var form = createView({ View: FormView, model: 'partner', @@ -1659,9 +1659,9 @@ QUnit.module('basic_fields', { assert.strictEqual(euroValues.length, 1, 'One one line has euro as a currency.'); - var zeroValues = list.$('td').filter(function () {return _.str.include($(this).text(), '0.00');}); - assert.strictEqual(zeroValues.length, 2, - 'Unset float values should be rendered as zeros.'); + var zeroValues = list.$('td.o_data_cell').filter(function () {return $(this).text() === '';}); + assert.strictEqual(zeroValues.length, 1, + 'Unset float values should be rendered as empty strings.'); // switch to edit mode var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector):contains($)'); -- cgit v1.2.3 From e1edd62320fef4991ba9554ee197021b45987a60 Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Fri, 5 May 2017 16:34:54 +0200 Subject: [FIX] web: toggle checkboxes when clicked in editable list view Previously, the checkbox was not checked when it was clicked in editable list view, it only opened the row but did not check the checkbox. --- addons/web/static/tests/fields/basic_fields_tests.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 6e007949ea7..04d0588bfab 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -237,10 +237,10 @@ QUnit.module('basic_fields', { assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 3, "should still have only 3 checked input"); - // Re-Edit the line to check the checkbox back + // Re-Edit the line to check the checkbox back but this time click on + // the checkbox directly in readonly mode ! $cell = list.$('tr.o_data_row:has(.o_checkbox input:not(:checked)) td:not(.o_list_record_selector)').first(); - $cell.click(); - $cell.find('.o_checkbox input:not(:checked)').click(); + $cell.find('.o_checkbox span').click(); // save list.$buttons.find('.o_form_button_save').click(); -- cgit v1.2.3 From 42d95cbfc3d85a8ab79e5ac6fceee5d8f7c6c550 Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Thu, 11 May 2017 13:29:52 +0200 Subject: [FIX] web: keep focus on checkboxes after rerendering Previously, when a checkbox was re-rendered, it was losing focus since it was removed and re-created. Now, if the checkbox itself is the origin point of the re-rendering, we give the focus to the newly re-rendered checkbox, resulting in a seamless experience just as if the checkbox was never removed and re-rendered. --- addons/web/static/tests/fields/basic_fields_tests.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 04d0588bfab..8417e503676 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -123,7 +123,7 @@ QUnit.module('basic_fields', { QUnit.module('FieldBoolean'); QUnit.test('boolean field in form view', function (assert) { - assert.expect(11); + assert.expect(12); var form = createView({ View: FormView, @@ -183,6 +183,12 @@ QUnit.module('basic_fields', { .trigger({type: "keyup", which: $.ui.keyCode.ENTER}); assert.strictEqual(form.$('.o_field_boolean input:checked').length, 1, "checkbox should now be checked"); + // blindly press enter again, it should uncheck the checkbox + $(document.activeElement).trigger({type: "keydown", which: $.ui.keyCode.ENTER}); + assert.strictEqual(form.$('.o_field_boolean input:checked').length, 0, + "checkbox should not be checked"); + // blindly press enter again, it should check the checkbox back + $(document.activeElement).trigger({type: "keydown", which: $.ui.keyCode.ENTER}); // save form.$buttons.find('.o_form_button_save').click(); -- cgit v1.2.3 From 1c5ea99b7b82c2b6f28ad1a3dbffc1300fda6466 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 4 May 2017 13:27:31 +0200 Subject: [FIX] web: display a translation alert when saving the form view In the form view, when the user saves a record (with a multilang instance), an alert is displayed to display all modified translatable fields. --- addons/web/static/tests/fields/basic_fields_tests.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 8417e503676..2c1d0520748 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -662,7 +662,7 @@ QUnit.module('basic_fields', { this.data.partner.fields.foo.translate = true; - var multi_lang = _t.database.multi_lang; + var multiLang = _t.database.multi_lang; _t.database.multi_lang = true; var form = createView({ @@ -707,7 +707,7 @@ QUnit.module('basic_fields', { assert.strictEqual($button.length, 0, "should not have a translate button in create mode"); form.destroy(); - _t.database.multi_lang = multi_lang; + _t.database.multi_lang = multiLang; }); @@ -875,7 +875,7 @@ QUnit.module('basic_fields', { this.data.partner.fields.txt.translate = true; - var multi_lang = _t.database.multi_lang; + var multiLang = _t.database.multi_lang; _t.database.multi_lang = true; var form = createView({ @@ -920,7 +920,7 @@ QUnit.module('basic_fields', { assert.strictEqual($button.length, 0, "should not have a translate button in create mode"); form.destroy(); - _t.database.multi_lang = multi_lang; + _t.database.multi_lang = multiLang; }); QUnit.module('FieldBinary'); -- cgit v1.2.3 From 932e8874004da7b0222cd1846eac090819d3ab07 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 15 May 2017 15:07:10 +0200 Subject: [FIX] web: datepicker did not select correct date after initial render --- addons/web/static/tests/fields/basic_fields_tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 2c1d0520748..7b9fbd061eb 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1257,7 +1257,7 @@ QUnit.module('basic_fields', { }); QUnit.test('date field in form view', function (assert) { - assert.expect(7); + assert.expect(8); var form = createView({ View: FormView, @@ -1290,6 +1290,7 @@ QUnit.module('basic_fields', { // click on the input and select another value form.$('.o_datepicker_input').click(); assert.ok(form.$('.bootstrap-datetimepicker-widget').length, 'datepicker should be open'); + assert.strictEqual(form.$('.day.active').data('day'), '02/03/2017', 'datepicker should be highlight February 3'); form.$('.bootstrap-datetimepicker-widget .picker-switch').first().click(); // Month selection form.$('.bootstrap-datetimepicker-widget .picker-switch').first().click(); // Year selection form.$('.bootstrap-datetimepicker-widget .year:contains(2017)').click(); @@ -1393,7 +1394,6 @@ QUnit.module('basic_fields', { form.destroy(); }); - QUnit.module('FieldDatetime'); QUnit.test('datetime field in form view', function (assert) { -- cgit v1.2.3