From 1ea7a3d6adcce54a258108ab33de8dd2379ae867 Mon Sep 17 00:00:00 2001 From: Pierre Paridans Date: Fri, 17 Mar 2023 09:36:36 +0000 Subject: [PATCH] [FIX] web: don't update related daterange field when not in the DOM This commit avoids to update the related daterange field (aka. end date when changing start date, and vice-versa) when this field is not present in the DOM (could be 'invisible' field or hidden column in list). Steps to reproduce: - Open Field Service - Switch to list view - hide the End date column - select record(s) to enter multi edit mode - click on the Start date of the selected record to open the date range picker - select a new range - click Apply ==> Error saying that cannot read setStartDate from undefined task-3200845 closes odoo/odoo#115766 X-original-commit: 9e00bd26ac43bfdaacd74de324ead84e4154a912 Signed-off-by: Aaron Bohy (aab) --- .../views/fields/daterange/daterange_field.js | 4 + .../views/fields/daterange_field_tests.js | 153 ++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/addons/web/static/src/views/fields/daterange/daterange_field.js b/addons/web/static/src/views/fields/daterange/daterange_field.js index 7ae6d9db5b3..43cfd1b1880 100644 --- a/addons/web/static/src/views/fields/daterange/daterange_field.js +++ b/addons/web/static/src/views/fields/daterange/daterange_field.js @@ -139,6 +139,10 @@ export class DateRangeField extends Component { const input = document.querySelector( `.o_field_daterange[name='${this.relatedDateRangeField}'] input` ); + if (!input) { + // Don't attempt to update the related daterange field if not present in the DOM + return; + } const target = window.$(input).data("daterangepicker"); target.setStartDate(picker.startDate); target.setEndDate(picker.endDate); diff --git a/addons/web/static/tests/views/fields/daterange_field_tests.js b/addons/web/static/tests/views/fields/daterange_field_tests.js index 174303f8964..48cb94e7a3b 100644 --- a/addons/web/static/tests/views/fields/daterange_field_tests.js +++ b/addons/web/static/tests/views/fields/daterange_field_tests.js @@ -815,4 +815,157 @@ QUnit.module("Fields", (hooks) => { ); } ); + + QUnit.test( + "Render with one visible field: start date [REQUIRE FOCUS]", + async function (assert) { + serverData.models.partner.fields.date_end = { string: "Date End", type: "date" }; + serverData.models.partner.records[0].date_end = "2017-02-08"; + + await makeView({ + type: "form", + resModel: "partner", + resId: 1, + serverData, + arch: ` +
+ + + `, + }); + + let fields = target.querySelectorAll(".o_field_daterange"); + // Check date range picker initialization + assert.containsOnce( + document.body, + ".daterangepicker", + "should initialize 1 date range picker" + ); + + // open the start date + await click(fields[0].querySelector("input")); + const datepicker = document.querySelector( + `.daterangepicker[data-name="${fields[0].getAttribute("name")}"]` + ); + + assert.isVisible(datepicker, "date range picker should be opened"); + assert.strictEqual( + datepicker.querySelector(".active.start-date").textContent, + "3", + "active start date should be '3' in date range picker" + ); + assert.strictEqual( + datepicker.querySelector(".active.end-date").textContent, + "8", + "active end date should be '8' in date range picker" + ); + + // Change date + await triggerEvent( + datepicker, + ".drp-calendar.left .available[data-title='r2c4']", + "mousedown" + ); + await triggerEvent( + datepicker, + ".drp-calendar.right .available[data-title='r2c0']", + "mousedown" + ); + await click(datepicker.querySelector(".applyBtn")); + + // Check date after change + assert.isNotVisible(datepicker, "date range picker should be closed"); + assert.strictEqual( + fields[0].querySelector("input").value, + "02/16/2017", + "the date should be '02/16/2017'" + ); + + // Save + await clickSave(target); + fields = target.querySelectorAll(".o_field_daterange"); + + // Check date after save + assert.strictEqual( + fields[0].querySelector("input").value, + "02/16/2017", + "the start date should be '02/16/2017' after save" + ); + } + ); + + QUnit.test("Render with one visible field: end date [REQUIRE FOCUS]", async function (assert) { + serverData.models.partner.fields.date_end = { string: "Date End", type: "date" }; + serverData.models.partner.records[0].date_end = "2017-02-08"; + + await makeView({ + type: "form", + resModel: "partner", + resId: 1, + serverData, + arch: ` +
+ + + `, + }); + + let fields = target.querySelectorAll(".o_field_daterange"); + // Check date range picker initialization + assert.containsOnce( + document.body, + ".daterangepicker", + "should initialize 1 date range picker" + ); + + // open the end date + await click(fields[0].querySelector("input")); + const datepicker = document.querySelector( + `.daterangepicker[data-name="${fields[0].getAttribute("name")}"]` + ); + + assert.isVisible(datepicker, "date range picker should be opened"); + assert.strictEqual( + datepicker.querySelector(".active.start-date").textContent, + "3", + "active start date should be '3' in date range picker" + ); + assert.strictEqual( + datepicker.querySelector(".active.end-date").textContent, + "8", + "active end date should be '8' in date range picker" + ); + + // Change date + await triggerEvent( + datepicker, + ".drp-calendar.left .available[data-title='r2c4']", + "mousedown" + ); + await triggerEvent( + datepicker, + ".drp-calendar.right .available[data-title='r2c0']", + "mousedown" + ); + await click(datepicker.querySelector(".applyBtn")); + + // Check date after change + assert.isNotVisible(datepicker, "date range picker should be closed"); + assert.strictEqual( + fields[0].querySelector("input").value, + "03/12/2017", + "the date should be '03/12/2017'" + ); + + // Save + await clickSave(target); + fields = target.querySelectorAll(".o_field_daterange"); + + // Check date after save + assert.strictEqual( + fields[0].querySelector("input").value, + "03/12/2017", + "the end date should be '02/13/2017' after save" + ); + }); });