Skip to content

Commit 91c0583

Browse files
committed
[IMP] side_panel: keep tabs visible and preserve scroll/section state
Before this commit: - Tabs scrolled with content and were not always visible. - Switching tabs reset scroll position and section open/close state. After this commit: - Tabs remain visible while scrolling. - Scroll and section states are preserved per tab. closes #6643 Task: 4752564 Signed-off-by: Rémi Rahir (rar) <rar@odoo.com>
1 parent 43821c1 commit 91c0583

File tree

3 files changed

+77
-26
lines changed

3 files changed

+77
-26
lines changed

src/components/side_panel/chart/main_chart_panel/main_chart_panel.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
import { Component } from "@odoo/owl";
1+
import { Component, useEffect, useRef } from "@odoo/owl";
22
import { ChartSidePanel, chartSidePanelComponentRegistry } from "..";
33
import { GRAY_100, GRAY_300, TEXT_BODY, TEXT_HEADING } from "../../../../constants";
44
import { Store, useLocalStore } from "../../../../store_engine";
5-
import { ChartDefinition, ChartType, SpreadsheetChildEnv, UID } from "../../../../types/index";
5+
import {
6+
ChartDefinition,
7+
ChartType,
8+
Pixel,
9+
Ref,
10+
SpreadsheetChildEnv,
11+
UID,
12+
} from "../../../../types/index";
613
import { css } from "../../../helpers/css";
714
import { Section } from "../../components/section/section";
815
import { ChartTypePicker } from "../chart_type_picker/chart_type_picker";
@@ -50,6 +57,11 @@ export class ChartPanel extends Component<Props, SpreadsheetChildEnv> {
5057
static template = "o-spreadsheet-ChartPanel";
5158
static components = { Section, ChartTypePicker };
5259
static props = { onCloseSidePanel: Function, figureId: String };
60+
private panelContentRef!: Ref<HTMLElement>;
61+
private scrollPositions: Record<"configuration" | "design", Pixel> = {
62+
configuration: 0,
63+
design: 0,
64+
};
5365

5466
store!: Store<MainChartPanelStore>;
5567

@@ -59,6 +71,26 @@ export class ChartPanel extends Component<Props, SpreadsheetChildEnv> {
5971

6072
setup(): void {
6173
this.store = useLocalStore(MainChartPanelStore);
74+
this.panelContentRef = useRef("panelContent");
75+
76+
useEffect(
77+
() => {
78+
const el = this.panelContentRef.el as HTMLElement;
79+
const activePanel = this.store.panel;
80+
if (el) {
81+
el.scrollTop = this.scrollPositions[activePanel];
82+
}
83+
},
84+
() => [this.store.panel]
85+
);
86+
}
87+
88+
switchPanel(panel: "configuration" | "design") {
89+
const el = this.panelContentRef.el as HTMLElement;
90+
if (el) {
91+
this.scrollPositions[this.store.panel] = el.scrollTop;
92+
}
93+
this.store.activatePanel(panel);
6294
}
6395

6496
updateChart<T extends ChartDefinition>(figureId: UID, updateDefinition: Partial<T>) {
Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,47 @@
11
<templates>
22
<t t-name="o-spreadsheet-ChartPanel">
3-
<div class="o-chart" t-if="figureId">
3+
<div class="o-chart d-flex flex-column h-100" t-if="figureId">
44
<div class="o-panel">
55
<div
66
class="o-panel-element o-panel-configuration"
77
t-att-class="store.panel !== 'configuration' ? 'inactive' : ''"
8-
t-on-click="() => this.store.activatePanel('configuration')">
8+
t-on-click="switchPanel.bind(this, 'configuration')">
99
<i class="fa fa-sliders"/>
1010
Configuration
1111
</div>
1212
<div
1313
class="o-panel-element o-panel-design"
1414
t-att-class="store.panel !== 'design' ? 'inactive' : ''"
15-
t-on-click="() => this.store.activatePanel('design')">
15+
t-on-click="switchPanel.bind(this, 'design')">
1616
<i class="fa fa-paint-brush"/>
1717
Design
1818
</div>
1919
</div>
2020

2121
<t t-set="definition" t-value="getChartDefinition(this.figureId)"/>
22-
<t t-if="store.panel === 'configuration'">
23-
<ChartTypePicker figureId="props.figureId" chartPanelStore="store"/>
24-
<t
25-
t-component="chartPanel.configuration"
26-
definition="definition"
27-
figureId="figureId"
28-
updateChart.bind="updateChart"
29-
canUpdateChart.bind="canUpdateChart"
30-
t-key="figureId + definition.type"
31-
/>
32-
</t>
33-
<t t-else="">
34-
<t
35-
t-component="chartPanel.design"
36-
definition="definition"
37-
figureId="figureId"
38-
updateChart.bind="updateChart"
39-
canUpdateChart.bind="canUpdateChart"
40-
t-key="figureId + definition.type"
41-
/>
42-
</t>
22+
<div class="o-panel-content overflow-y-auto" t-ref="panelContent">
23+
<div t-att-class="store.panel !== 'configuration' ? 'd-none' : ''">
24+
<ChartTypePicker figureId="props.figureId" chartPanelStore="store"/>
25+
<t
26+
t-component="chartPanel.configuration"
27+
definition="definition"
28+
figureId="figureId"
29+
updateChart.bind="updateChart"
30+
canUpdateChart.bind="canUpdateChart"
31+
t-key="figureId + definition.type"
32+
/>
33+
</div>
34+
<div t-att-class="store.panel !== 'design' ? 'd-none' : ''">
35+
<t
36+
t-component="chartPanel.design"
37+
definition="definition"
38+
figureId="figureId"
39+
updateChart.bind="updateChart"
40+
canUpdateChart.bind="canUpdateChart"
41+
t-key="figureId + definition.type"
42+
/>
43+
</div>
44+
</div>
4345
</div>
4446
</t>
4547
</templates>

tests/figures/chart/charts_component.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,23 @@ describe("charts", () => {
11001100
expect(fixture.querySelector(".o-chart")).toBeFalsy();
11011101
});
11021102

1103+
test("restores scroll position when switching tabs in side panel", async () => {
1104+
createTestChart("basicChart");
1105+
await mountSpreadsheet();
1106+
await openChartDesignSidePanel(model, env, fixture, chartId);
1107+
1108+
const chartPanel = fixture.querySelector(".o-panel-content")!;
1109+
chartPanel.scrollTop = 100;
1110+
1111+
const configTab = fixture.querySelector(".o-panel-element.inactive")!;
1112+
await click(configTab);
1113+
expect(chartPanel.scrollTop).toBe(0);
1114+
1115+
const designTab = fixture.querySelector(".o-panel-element.inactive")!;
1116+
await click(designTab);
1117+
expect(chartPanel.scrollTop).toBe(100);
1118+
});
1119+
11031120
describe.each(TEST_CHART_TYPES)("selecting other chart will adapt sidepanel", (chartType) => {
11041121
test.each(["click", "SELECT_FIGURE command"])("when using %s", async (selectMethod: string) => {
11051122
createTestChart(chartType);

0 commit comments

Comments
 (0)