diff --git a/packages/o-spreadsheet-engine/src/types/chart/chart.ts b/packages/o-spreadsheet-engine/src/types/chart/chart.ts
index d5aa66502e..dd96a6da67 100644
--- a/packages/o-spreadsheet-engine/src/types/chart/chart.ts
+++ b/packages/o-spreadsheet-engine/src/types/chart/chart.ts
@@ -235,6 +235,7 @@ export interface ChartCreationContext {
readonly treemapColoringOptions?: TreeMapColoringOptions;
readonly zoomable?: boolean;
readonly humanize?: boolean;
+ readonly slicesColors?: string[];
}
export type ChartAxisFormats = { [axisId: string]: Format | undefined } | undefined;
diff --git a/packages/o-spreadsheet-engine/src/types/chart/pie_chart.ts b/packages/o-spreadsheet-engine/src/types/chart/pie_chart.ts
index 6070949b93..0f75b4e856 100644
--- a/packages/o-spreadsheet-engine/src/types/chart/pie_chart.ts
+++ b/packages/o-spreadsheet-engine/src/types/chart/pie_chart.ts
@@ -4,6 +4,7 @@ import { CommonChartDefinition } from "./common_chart";
export interface PieChartDefinition extends CommonChartDefinition {
readonly type: "pie";
+ readonly slicesColors?: string[];
readonly aggregated?: boolean;
readonly isDoughnut?: boolean;
readonly showValues?: boolean;
diff --git a/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.ts b/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.ts
index b2fe4ddfe2..8cc2339c2c 100644
--- a/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.ts
+++ b/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.ts
@@ -1,8 +1,11 @@
-import { PieChartDefinition } from "@odoo/o-spreadsheet-engine/types/chart";
+import { deepCopy } from "@odoo/o-spreadsheet-engine";
+import { PieChartDefinition, PieChartRuntime } from "@odoo/o-spreadsheet-engine/types/chart";
import { SpreadsheetChildEnv } from "@odoo/o-spreadsheet-engine/types/spreadsheet_env";
import { DEFAULT_DOUGHNUT_CHART_HOLE_SIZE } from "@odoo/o-spreadsheet-engine/xlsx/constants";
-import { Component } from "@odoo/owl";
+import { Component, useState } from "@odoo/owl";
import { Checkbox } from "../../components/checkbox/checkbox";
+import { SidePanelCollapsible } from "../../components/collapsible/side_panel_collapsible";
+import { RoundColorPicker } from "../../components/round_color_picker/round_color_picker";
import { Section } from "../../components/section/section";
import { GeneralDesignEditor } from "../building_blocks/general_design/general_design_editor";
import { ChartHumanizeNumbers } from "../building_blocks/humanize_numbers/humanize_numbers";
@@ -24,9 +27,24 @@ export class PieChartDesignPanel extends Component<
PieHoleSize,
Checkbox,
ChartHumanizeNumbers,
+ SidePanelCollapsible,
+ RoundColorPicker,
};
static props = ChartSidePanelPropsObject;
+ protected state = useState({ index: 0 });
+
+ private runtime!: PieChartRuntime;
+
+ setup() {
+ super.setup();
+ this.runtime = this.env.model.getters.getChartRuntime(this.props.chartId) as PieChartRuntime;
+ }
+
+ getLabels() {
+ return this.runtime.chartJsConfig.data.labels;
+ }
+
onPieHoleSizeChange(pieHolePercentage: number) {
this.props.updateChart(this.props.chartId, {
...this.props.definition,
@@ -36,4 +54,30 @@ export class PieChartDesignPanel extends Component<
get defaultHoleSize() {
return DEFAULT_DOUGHNUT_CHART_HOLE_SIZE;
}
+
+ updateEditedValues(ev: Event) {
+ this.state.index = (ev.target as HTMLSelectElement).selectedIndex;
+ }
+
+ updateSliceColor(color: string) {
+ let slicesColors = deepCopy(this.props.definition.slicesColors);
+ if (!slicesColors) {
+ slicesColors = Array(this.getLabels()?.length).fill("");
+ }
+ slicesColors[this.state.index] = color;
+ this.props.updateChart(this.props.chartId, {
+ ...this.props.definition,
+ slicesColors,
+ });
+ }
+
+ getSliceColor() {
+ const slicesColors = this.props.definition.slicesColors;
+ if (slicesColors?.[this.state.index]) {
+ return slicesColors?.[this.state.index];
+ }
+ const dataSets = this.runtime.chartJsConfig.data.datasets;
+ const color = dataSets[0]?.backgroundColor?.[this.state.index];
+ return color;
+ }
}
diff --git a/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.xml b/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.xml
index 7201dcb750..8e78aece27 100644
--- a/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.xml
+++ b/src/components/side_panel/chart/pie_chart/pie_chart_design_panel.xml
@@ -16,5 +16,29 @@
/>
+
+
+
+
+
+
+
diff --git a/src/helpers/figures/charts/pie_chart.ts b/src/helpers/figures/charts/pie_chart.ts
index 164ad4116c..f599104f86 100644
--- a/src/helpers/figures/charts/pie_chart.ts
+++ b/src/helpers/figures/charts/pie_chart.ts
@@ -51,6 +51,7 @@ export class PieChart extends AbstractChart {
readonly background?: Color;
readonly legendPosition: LegendPosition;
readonly type = "pie";
+ readonly slicesColors?: string[];
readonly aggregated?: boolean;
readonly dataSetsHaveTitle: boolean;
readonly isDoughnut?: boolean;
@@ -73,6 +74,7 @@ export class PieChart extends AbstractChart {
this.isDoughnut = definition.isDoughnut;
this.showValues = definition.showValues;
this.pieHolePercentage = definition.pieHolePercentage;
+ this.slicesColors = definition.slicesColors;
}
static transformDefinition(
@@ -104,6 +106,7 @@ export class PieChart extends AbstractChart {
pieHolePercentage: context.pieHolePercentage,
showValues: context.showValues,
humanize: context.humanize,
+ slicesColors: context.slicesColors,
};
}
@@ -145,6 +148,7 @@ export class PieChart extends AbstractChart {
showValues: this.showValues,
pieHolePercentage: this.pieHolePercentage,
humanize: this.humanize,
+ slicesColors: this.slicesColors,
};
}
diff --git a/src/helpers/figures/charts/runtime/chartjs_dataset.ts b/src/helpers/figures/charts/runtime/chartjs_dataset.ts
index 6a8142b9d8..20be2d90f2 100644
--- a/src/helpers/figures/charts/runtime/chartjs_dataset.ts
+++ b/src/helpers/figures/charts/runtime/chartjs_dataset.ts
@@ -277,7 +277,10 @@ export function getPieChartDatasets(
const { dataSetsValues } = args;
const dataSets: ChartDataset<"pie">[] = [];
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
- const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
+ const backgroundColor = getPieColors(
+ new ColorGenerator(dataSetsLength, definition.slicesColors),
+ dataSetsValues
+ );
for (const { label, data, hidden } of dataSetsValues) {
if (hidden) {
continue;
diff --git a/src/helpers/figures/charts/runtime/chartjs_legend.ts b/src/helpers/figures/charts/runtime/chartjs_legend.ts
index bd0f621581..076dcdec59 100644
--- a/src/helpers/figures/charts/runtime/chartjs_legend.ts
+++ b/src/helpers/figures/charts/runtime/chartjs_legend.ts
@@ -17,6 +17,7 @@ import {
ChartWithDataSetDefinition,
GenericDefinition,
LineChartDefinition,
+ PieChartDefinition,
SunburstChartDefinition,
SunburstChartJSDataset,
WaterfallChartDefinition,
@@ -70,12 +71,15 @@ export function getLineChartLegend(
}
export function getPieChartLegend(
- definition: GenericDefinition,
+ definition: GenericDefinition,
args: ChartRuntimeGenerationArgs
): ChartLegend {
const { dataSetsValues } = args;
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
- const colors = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
+ const colors = getPieColors(
+ new ColorGenerator(dataSetsLength, definition.slicesColors),
+ dataSetsValues
+ );
const fontColor = chartFontColor(definition.background);
return {
...getLegendDisplayOptions(definition, args),
diff --git a/tests/figures/chart/charts_component.test.ts b/tests/figures/chart/charts_component.test.ts
index b88574fc34..63f5de28ff 100644
--- a/tests/figures/chart/charts_component.test.ts
+++ b/tests/figures/chart/charts_component.test.ts
@@ -731,6 +731,41 @@ describe("charts", () => {
]);
});
+ test("can edit pie chart slices color", async () => {
+ createChart(
+ model,
+ {
+ dataSets: [
+ { dataRange: "B1:B4", label: "serie_1" },
+ { dataRange: "C1:C4", label: "serie_2" },
+ ],
+ labelRange: "A2:A4",
+ type: "pie",
+ },
+ chartId
+ );
+ await mountChartSidePanel();
+ await openChartDesignSidePanel(model, env, fixture, chartId);
+
+ const color_menu = fixture.querySelectorAll(".o-round-color-picker-button")[1];
+
+ await click(color_menu);
+ await click(fixture, ".o-color-picker-line-item[data-color='#EFEFEF'");
+ //@ts-ignore
+ expect(model.getters.getChartDefinition(chartId).slicesColors).toEqual(["#EFEFEF", "", ""]);
+ setInputValueAndTrigger(".pie-slice-selector", "P3");
+
+ await click(color_menu);
+ await click(fixture, ".o-color-picker-line-item[data-color='#FF0000'");
+ //@ts-ignore
+
+ expect(model.getters.getChartDefinition(chartId).slicesColors).toEqual([
+ "#EFEFEF",
+ "",
+ "#FF0000",
+ ]);
+ });
+
test("can edit chart data series vertical axis", async () => {
createChart(
model,
diff --git a/tests/figures/chart/pie_chart_plugin.test.ts b/tests/figures/chart/pie_chart_plugin.test.ts
index b8d405b9e2..eb4bc0a068 100644
--- a/tests/figures/chart/pie_chart_plugin.test.ts
+++ b/tests/figures/chart/pie_chart_plugin.test.ts
@@ -28,6 +28,7 @@ describe("pie chart", () => {
pieHolePercentage: 0,
showValues: false,
humanize: false,
+ slicesColors: [],
});
});
diff --git a/tests/test_helpers/chart_helpers.ts b/tests/test_helpers/chart_helpers.ts
index b29a87f445..d82c427300 100644
--- a/tests/test_helpers/chart_helpers.ts
+++ b/tests/test_helpers/chart_helpers.ts
@@ -136,4 +136,5 @@ export const GENERAL_CHART_CREATION_CONTEXT: Required = {
showHeaders: true,
zoomable: false,
humanize: false,
+ slicesColors: [],
};