Skip to content

Commit 42003b1

Browse files
committed
[IMP] LineChart: cumulative chart
This commit introduces a new feature to the LineChart that allows users to switch between cumulative and non-cumulative data modes using a checkbox in the side panel. When the cumulative mode is selected, the chart shows cumulative data, providing a comprehensive view of data progression. Task-3420844 closes #2851 X-original-commit: 1f43919 Signed-off-by: Adrien Minne (adrm) <adrm@odoo.com> Signed-off-by: Aashish Thakur (aath) <aath@odoo.com>
1 parent bedec13 commit 42003b1

File tree

11 files changed

+74
-0
lines changed

11 files changed

+74
-0
lines changed

src/components/side_panel/chart/line_chart/line_chart_config_panel.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,10 @@ export class LineConfigPanel extends LineBarPieConfigPanel {
2929
aggregated: ev.target.checked,
3030
});
3131
}
32+
33+
onUpdateCumulative(ev) {
34+
this.props.updateChart(this.props.figureId, {
35+
cumulative: ev.target.checked,
36+
});
37+
}
3238
}

src/components/side_panel/chart/line_chart/line_chart_config_panel.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@
1414
Stacked linechart
1515
</label>
1616
</div>
17+
<div class="o-checkbox">
18+
<label>
19+
<input
20+
type="checkbox"
21+
name="cumulative"
22+
t-att-checked="props.definition.cumulative"
23+
t-on-change="onUpdateCumulative"
24+
class="align-middle"
25+
/>
26+
Cumulative data
27+
</label>
28+
</div>
1729
</div>
1830
<div class="o-section o-data-series">
1931
<div class="o-section-title">Data Series</div>

src/helpers/figures/charts/chart_factory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ export function getSmartChartDefinition(zone: Zone, getters: Getters): ChartDefi
176176
labelsAsText: false,
177177
stacked: false,
178178
aggregated: false,
179+
cumulative: false,
179180
labelRange: labelRangeXc,
180181
type: "line",
181182
dataSetsHaveTitle,

src/helpers/figures/charts/line_chart.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export class LineChart extends AbstractChart {
6666
readonly aggregated?: boolean;
6767
readonly type = "line";
6868
readonly dataSetsHaveTitle: boolean;
69+
readonly cumulative: boolean;
6970

7071
constructor(definition: LineChartDefinition, sheetId: UID, getters: CoreGetters) {
7172
super(definition, sheetId, getters);
@@ -83,6 +84,7 @@ export class LineChart extends AbstractChart {
8384
this.stacked = definition.stacked;
8485
this.aggregated = definition.aggregated;
8586
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
87+
this.cumulative = definition.cumulative;
8688
}
8789

8890
static validateChartDefinition(
@@ -112,6 +114,7 @@ export class LineChart extends AbstractChart {
112114
labelRange: context.auxiliaryRange || undefined,
113115
stacked: false,
114116
aggregated: false,
117+
cumulative: false,
115118
};
116119
}
117120

@@ -140,6 +143,7 @@ export class LineChart extends AbstractChart {
140143
labelsAsText: this.labelsAsText,
141144
stacked: this.stacked,
142145
aggregated: this.aggregated,
146+
cumulative: this.cumulative,
143147
};
144148
}
145149

@@ -396,6 +400,17 @@ export function createLineChartRuntime(chart: LineChart, getters: Getters): Line
396400
if (chart.stacked) {
397401
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
398402
}
403+
if (chart.cumulative) {
404+
let accumulator = 0;
405+
data = data.map((value) => {
406+
if (!isNaN(value)) {
407+
accumulator += parseFloat(value);
408+
return accumulator;
409+
}
410+
return value;
411+
});
412+
}
413+
399414
const backgroundColor = rgbaToHex(backgroundRGBA);
400415

401416
const dataset: ChartDataSets = {

src/types/chart/chart.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export interface ExcelChartDefinition {
5757
readonly verticalAxisPosition: VerticalAxisPosition;
5858
readonly legendPosition: LegendPosition;
5959
readonly stacked?: boolean;
60+
readonly cumulative?: boolean;
6061
}
6162

6263
export interface ChartCreationContext {

src/types/chart/line_chart.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface LineChartDefinition {
1414
readonly labelsAsText: boolean;
1515
readonly stacked: boolean;
1616
readonly aggregated?: boolean;
17+
readonly cumulative: boolean;
1718
}
1819

1920
export type LineChartRuntime = {

src/xlsx/conversion/figure_conversion.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ function convertChartData(chartData: ExcelChartDefinition): ChartDefinition | un
9393
legendPosition: chartData.legendPosition,
9494
stacked: chartData.stacked || false,
9595
aggregated: false,
96+
cumulative: chartData.cumulative || false,
9697
labelsAsText: false,
9798
};
9899
}

tests/collaborative/collaborative_history.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ describe("Collaborative local history", () => {
458458
verticalAxisPosition: "left",
459459
title: "Line",
460460
stacked: false,
461+
cumulative: false,
461462
},
462463
},
463464
],

tests/menu_item_insert_chart.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ describe("Insert chart menu item", () => {
391391
payload.definition.dataSetsHaveTitle = true;
392392
payload.definition.labelRange = "C1:C4";
393393
payload.definition.type = "line";
394+
payload.definition.cumulative = false;
394395
payload.definition.labelsAsText = false;
395396
expect(dispatchSpy).toHaveBeenCalledWith("CREATE_CHART", payload);
396397
});
@@ -404,6 +405,7 @@ describe("Insert chart menu item", () => {
404405
payload.definition.dataSetsHaveTitle = true;
405406
payload.definition.labelRange = "C1:C4";
406407
payload.definition.type = "line";
408+
payload.definition.cumulative = false;
407409
payload.definition.labelsAsText = false;
408410
expect(dispatchSpy).toHaveBeenCalledWith("CREATE_CHART", payload);
409411
});
@@ -426,6 +428,7 @@ describe("Insert chart menu item", () => {
426428
payload.definition.labelRange = "F1:F5";
427429
payload.definition.legendPosition = "top";
428430
payload.definition.type = "line";
431+
payload.definition.cumulative = false;
429432
payload.definition.labelsAsText = false;
430433
expect(dispatchSpy).toHaveBeenCalledWith("CREATE_CHART", payload);
431434
});
@@ -480,6 +483,7 @@ describe("Insert chart menu item", () => {
480483
payload.definition.dataSets = ["L1:L3"];
481484
payload.definition.labelRange = "K1:K3";
482485
payload.definition.type = "line";
486+
payload.definition.cumulative = false;
483487
payload.definition.labelsAsText = false;
484488
expect(dispatchSpy).toHaveBeenCalledWith("CREATE_CHART", payload);
485489
expect(zoneToXc(model.getters.getSelectedZone())).toBe("K1:L3");
@@ -499,6 +503,7 @@ describe("Insert chart menu item", () => {
499503
payload.definition.dataSets = ["L1:L3"];
500504
payload.definition.labelRange = "K1:K3";
501505
payload.definition.type = "line";
506+
payload.definition.cumulative = false;
502507
payload.definition.labelsAsText = false;
503508
expect(dispatchSpy).toHaveBeenCalledWith("CREATE_CHART", payload);
504509
expect(zoneToXc(model.getters.getSelectedZone())).toBe("K1:L3");

tests/plugins/chart/basic_chart.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,6 +1963,36 @@ describe("Chart evaluation", () => {
19631963
).toBe("#REF");
19641964
});
19651965
});
1966+
1967+
describe("Cumulative Data line chart", () => {
1968+
test("Chart to display cumulative data", () => {
1969+
createChart(
1970+
model,
1971+
{
1972+
dataSets: ["B2:B8"],
1973+
dataSetsHaveTitle: true,
1974+
labelRange: "A2",
1975+
type: "line",
1976+
cumulative: false,
1977+
},
1978+
"1"
1979+
);
1980+
1981+
const chartData = (model.getters.getChartRuntime("1") as LineChartRuntime).chartJsConfig.data!
1982+
.datasets![0].data;
1983+
const initialData = [11, 12, 13, "P4", 30];
1984+
const expectedCumulativeData = [11, 23, 36, "P4", 66];
1985+
1986+
expect(chartData).toEqual(initialData);
1987+
1988+
updateChart(model, "1", { cumulative: true });
1989+
const updatedChartData = (model.getters.getChartRuntime("1") as LineChartRuntime).chartJsConfig
1990+
.data!.datasets![0].data;
1991+
1992+
expect(updatedChartData).toEqual(expectedCumulativeData);
1993+
});
1994+
});
1995+
19661996
test("creating chart with single dataset should have legend position set as none, followed by changing it to top", async () => {
19671997
createChart(
19681998
model,

0 commit comments

Comments
 (0)