diff --git a/addons/web/static/src/webclient/settings_form_view/settings/settings_page.js b/addons/web/static/src/webclient/settings_form_view/settings/settings_page.js index b69069473b0..eb1cf876bf0 100644 --- a/addons/web/static/src/webclient/settings_form_view/settings/settings_page.js +++ b/addons/web/static/src/webclient/settings_form_view/settings/settings_page.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { ActionSwiper } from "@web/core/action_swiper/action_swiper"; -const { Component, useState } = owl; +const { Component, useState, useRef, useEffect } = owl; export class SettingsPage extends Component { setup() { @@ -13,6 +13,20 @@ export class SettingsPage extends Component { if (this.props.modules) { this.state.selectedTab = this.props.initialTab || this.props.modules[0].key; } + + this.settingsRef = useRef("settings"); + this.scrollMap = Object.create(null); + useEffect( + (settingsEl, currentTab) => { + if (!settingsEl) { + return; + } + + const { scrollTop } = this.scrollMap[currentTab] || 0; + settingsEl.scrollTop = scrollTop; + }, + () => [this.settingsRef.el, this.state.selectedTab] + ); } getCurrentIndex() { @@ -41,6 +55,10 @@ export class SettingsPage extends Component { } onSettingTabClick(key) { + if (this.settingsRef.el) { + const { scrollTop } = this.settingsRef.el; + this.scrollMap[this.state.selectedTab] = { scrollTop }; + } this.state.selectedTab = key; this.env.searchState.value = ""; } diff --git a/addons/web/static/src/webclient/settings_form_view/settings/settings_page.xml b/addons/web/static/src/webclient/settings_form_view/settings/settings_page.xml index 26584c4ef0c..9336eb218d0 100644 --- a/addons/web/static/src/webclient/settings_form_view/settings/settings_page.xml +++ b/addons/web/static/src/webclient/settings_form_view/settings/settings_page.xml @@ -18,7 +18,7 @@ animationOnMove="false" animationType="'forwards'" swipeDistanceRatio="6"> -
+
diff --git a/addons/web/static/tests/webclient/settings_form_view/settings_form_view_tests.js b/addons/web/static/tests/webclient/settings_form_view/settings_form_view_tests.js index 1c4f3d38142..d715da92c40 100644 --- a/addons/web/static/tests/webclient/settings_form_view/settings_form_view_tests.js +++ b/addons/web/static/tests/webclient/settings_form_view/settings_form_view_tests.js @@ -1526,4 +1526,65 @@ QUnit.module("SettingsFormView", (hooks) => { `focusin: `, ]); }); + + QUnit.test("settings form keeps scrolling by app", async (assert) => { + const oldHeight = target.style.getPropertyValue("height"); + target.style.setProperty("height", "200px"); + registerCleanup(() => { + target.style.setProperty("height", oldHeight); + }); + + await makeView({ + type: "form", + resModel: "res.config.settings", + serverData, + arch: ` +
+
+
+
+

Title of group Bar

+
+










+










+










+
+
+
+ +
+

Title of group Other

+
+
+










+










+










+
+
+
+
+
+
+ `, + }); + + // constrain o_content to have height for its children to be scrollable + target.querySelector(".o_content").style.setProperty("height", "200px"); + + const scrollingEl = target.querySelector(".settings"); + assert.strictEqual(scrollingEl.scrollTop, 0); + + await click(target.querySelector(".settings_tab [data-key='otherapp']")); + assert.strictEqual(scrollingEl.scrollTop, 0); + target.querySelector("#deepDivOther").scrollIntoView(); + + const scrollTop = scrollingEl.scrollTop; + assert.ok(scrollTop > 0); + + await click(target.querySelector(".settings_tab [data-key='crm']")); + assert.strictEqual(scrollingEl.scrollTop, 0); + + await click(target.querySelector(".settings_tab [data-key='otherapp']")); + assert.strictEqual(scrollingEl.scrollTop, scrollTop); + }); });