From 7bc53ac30ecadbb1e94051edd29c701679cd6de0 Mon Sep 17 00:00:00 2001 From: Aaron Bohy <aab@odoo.com> Date: Thu, 11 Apr 2019 13:35:49 +0000 Subject: [PATCH] [FIX] web: crash in editable lists with date field Assume an editable list view with a date(time) widget, click to edit a line, focus the date field (the datepicker opens), press ESC: there is a crash in the lib, and the datepicker remains open forever. This fix is twofold: - we added a check in the lib to prevent it from crashing (it is easily reproducible: it crashes when an opened datepicker is removed from the DOM). - we added an event handler of ESC keydown event to hide the datepicker before the field is removed from the DOM. --- .../static/lib/tempusdominus/tempusdominus.js | 3 +- .../web/static/src/js/widgets/date_picker.js | 12 ++++++ addons/web/static/tests/views/list_tests.js | 37 ++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/addons/web/static/lib/tempusdominus/tempusdominus.js b/addons/web/static/lib/tempusdominus/tempusdominus.js index ffca0c8e6325..4eaf0df2a600 100644 --- a/addons/web/static/lib/tempusdominus/tempusdominus.js +++ b/addons/web/static/lib/tempusdominus/tempusdominus.js @@ -2754,7 +2754,8 @@ var TempusDominusBootstrap4 = function ($) { if ($target.length === 0) { return; } - if (config._options.debug || window.debug) { + // /!\ ODOO FIX: check on 'config' existence added by odoo + if (config && config._options.debug || window.debug) { return; } TempusDominusBootstrap4._jQueryInterface.call($target, 'hide', event); diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js index 367ab23178d7..57c935905e5e 100644 --- a/addons/web/static/src/js/widgets/date_picker.js +++ b/addons/web/static/src/js/widgets/date_picker.js @@ -15,6 +15,7 @@ var DateWidget = Widget.extend({ 'change.datetimepicker': 'changeDatetime', 'change .o_datepicker_input': 'changeDatetime', 'input input': '_onInput', + 'keydown': '_onKeydown', 'show.datetimepicker': '_onDateTimePickerShow', }, /** @@ -239,6 +240,17 @@ var DateWidget = Widget.extend({ this.$input.select(); } }, + /** + * @private + * @param {KeyEvent} ev + */ + _onKeydown: function (ev) { + if (ev.which === $.ui.keyCode.ESCAPE) { + this.__libInput++; + this.$el.datetimepicker('hide'); + this.__libInput--; + } + }, /** * Prevents 'input' events triggered by the library to bubble up, as they * might have unwanted effects (like triggering 'field_changed' events in diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index c81a4e48db2b..5a8e19b8fb73 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -298,7 +298,42 @@ QUnit.module('Views', { list.destroy(); }); - QUnit.test('editable list datetimepicker destroy widget', async function (assert) { + QUnit.test('editable list datetimepicker destroy widget (edition)', async function (assert) { + assert.expect(6); + var eventPromise = testUtils.makeTestPromise(); + + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '<tree editable="top">' + + '<field name="date"/>' + + '</tree>', + }); + list.$el.on({ + 'show.datetimepicker': async function () { + assert.containsOnce(list, '.o_selected_row'); + assert.containsOnce($('body'), '.bootstrap-datetimepicker-widget'); + + await testUtils.fields.triggerKeydown(list.$('.o_datepicker_input'), 'escape'); + + assert.containsNone(list, '.o_selected_row'); + assert.containsNone($('body'), '.bootstrap-datetimepicker-widget'); + + eventPromise.resolve(); + } + }); + + assert.containsN(list, '.o_data_row', 4); + assert.containsNone(list, '.o_selected_row'); + + await testUtils.dom.click(list.$('.o_data_cell:first')); + + await eventPromise; + list.destroy(); + }); + + QUnit.test('editable list datetimepicker destroy widget (new line)', async function (assert) { assert.expect(7); var eventPromise = testUtils.makeTestPromise(); -- GitLab