Skip to content

Commit

Permalink
[IMP] charts: add radar chart
Browse files Browse the repository at this point in the history
Task Description

This task aims to add the new Radar chart type.

Related Task(s)

closes #5095

Task: 3633666
Signed-off-by: Lucas Lefèvre (lul) <[email protected]>
  • Loading branch information
anhe-odoo committed Oct 21, 2024
1 parent 46aeef4 commit 1e10d97
Show file tree
Hide file tree
Showing 36 changed files with 6,820 additions and 1,968 deletions.
18 changes: 18 additions & 0 deletions demo/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,24 @@ export const demoData = {
showConnectorLines: true,
},
},
{
id: "9",
x: 100,
y: 1175,
height: 300,
width: 500,
tag: "chart",
data: {
type: "radar",
dataSetsHaveTitle: true,
background: "#FFFFFF",
dataSets: [{ dataRange: "Sheet1!B26:B35" }, { dataRange: "Sheet1!C26:C35" }],
legendPosition: "top",
labelRange: "Sheet1!A27:A35",
title: { text: "Radar" },
aggregated: false,
},
},
],
tables: [],
areGridLinesVisible: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,4 @@ export class BarConfigPanel extends GenericChartConfigPanel {
stacked,
});
}

onUpdateAggregated(aggregated: boolean) {
this.props.updateChart(this.props.figureId, {
aggregated,
});
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, useState } from "@odoo/owl";
import {
ChartWithAxisDefinition,
ChartWithDataSetDefinition,
Color,
DispatchResult,
SpreadsheetChildEnv,
Expand All @@ -19,10 +19,10 @@ export interface AxisDefinition {

interface Props {
figureId: UID;
definition: ChartWithAxisDefinition | WaterfallChartDefinition;
definition: ChartWithDataSetDefinition | WaterfallChartDefinition;
updateChart: (
figureId: UID,
definition: Partial<ChartWithAxisDefinition | WaterfallChartDefinition>
definition: Partial<ChartWithDataSetDefinition | WaterfallChartDefinition>
) => DispatchResult;
axesList: AxisDefinition[];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createValidRange, spreadRange } from "../../../../../helpers";
import { createDataSets } from "../../../../../helpers/figures/charts";
import { _t } from "../../../../../translation";
import {
ChartWithAxisDefinition,
ChartWithDataSetDefinition,
CommandResult,
CustomizedDataSet,
DispatchResult,
Expand All @@ -19,9 +19,12 @@ import { ChartLabelRange } from "../label_range/label_range";

interface Props {
figureId: UID;
definition: ChartWithAxisDefinition;
canUpdateChart: (figureId: UID, definition: Partial<ChartWithAxisDefinition>) => DispatchResult;
updateChart: (figureId: UID, definition: Partial<ChartWithAxisDefinition>) => DispatchResult;
definition: ChartWithDataSetDefinition;
canUpdateChart: (
figureId: UID,
definition: Partial<ChartWithDataSetDefinition>
) => DispatchResult;
updateChart: (figureId: UID, definition: Partial<ChartWithDataSetDefinition>) => DispatchResult;
}

interface ChartPanelState {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Component, useState } from "@odoo/owl";
import { getColorsPalette, getNthColor, toHex } from "../../../../../helpers";
import {
ChartWithDataSetDefinition,
DispatchResult,
SpreadsheetChildEnv,
UID,
} from "../../../../../types";
import { SidePanelCollapsible } from "../../../components/collapsible/side_panel_collapsible";
import { RoundColorPicker } from "../../../components/round_color_picker/round_color_picker";
import { Section } from "../../../components/section/section";

interface Props {
figureId: UID;
definition: ChartWithDataSetDefinition;
canUpdateChart: (
figureID: UID,
definition: Partial<ChartWithDataSetDefinition>
) => DispatchResult;
updateChart: (figureId: UID, definition: Partial<ChartWithDataSetDefinition>) => DispatchResult;
}

export class SeriesDesignEditor extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-SeriesDesignEditor";
static components = {
SidePanelCollapsible,
Section,
RoundColorPicker,
};
static props = {
figureId: String,
definition: Object,
updateChart: Function,
canUpdateChart: Function,
slots: { type: Object, optional: true },
};

protected state = useState({ index: 0 });

getDataSeries() {
const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
if (!runtime || !("chartJsConfig" in runtime)) {
return [];
}
return runtime.chartJsConfig.data.datasets.map((d) => d.label);
}

updateSerieEditor(ev) {
this.state.index = ev.target.selectedIndex;
}

updateDataSeriesColor(color: string) {
const dataSets = this.props.definition.dataSets;
if (!dataSets?.[this.state.index]) return;
dataSets[this.state.index] = {
...dataSets[this.state.index],
backgroundColor: color,
};
this.props.updateChart(this.props.figureId, { dataSets });
}

getDataSerieColor() {
const dataSets = this.props.definition.dataSets;
if (!dataSets?.[this.state.index]) return "";
const color = dataSets[this.state.index].backgroundColor;
return color
? toHex(color)
: getNthColor(this.state.index, getColorsPalette(this.props.definition.dataSets.length));
}

updateDataSeriesLabel(ev) {
const label = ev.target.value;
const dataSets = this.props.definition.dataSets;
if (!dataSets?.[this.state.index]) return;
dataSets[this.state.index] = {
...dataSets[this.state.index],
label,
};
this.props.updateChart(this.props.figureId, { dataSets });
}

getDataSerieLabel() {
const dataSets = this.props.definition.dataSets;
return dataSets[this.state.index]?.label || this.getDataSeries()[this.state.index];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<templates>
<t t-name="o-spreadsheet-SeriesDesignEditor">
<SidePanelCollapsible collapsedAtInit="true" title.translate="Data Series">
<t t-set-slot="content">
<Section class="'pt-0 pb-0'">
<select
class="o-input data-series-selector"
t-model="state.label"
t-on-change="(ev) => this.updateSerieEditor(ev)">
<t t-foreach="getDataSeries()" t-as="serie" t-key="serie_index">
<option
t-att-value="serie"
t-att-selected="state.index === serie_index"
t-esc="serie"
/>
</t>
</select>
<Section class="'px-0'">
<div class="d-flex align-items-center">
<span class="o-section-title mb-0 pe-2">Series color</span>
<RoundColorPicker
currentColor="getDataSerieColor()"
onColorPicked.bind="updateDataSeriesColor"
/>
</div>
</Section>
<Section class="'pt-0 px-0'" title.translate="Series name">
<input
class="o-input o-serie-label-editor"
type="text"
t-att-value="getDataSerieLabel()"
t-on-change="(ev) => this.updateDataSeriesLabel(ev)"
/>
</Section>
</Section>
<t t-slot="data-series-extension" index="state.index"/>
</t>
</SidePanelCollapsible>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { Component } from "@odoo/owl";
import { getColorsPalette, getNthColor, setColorAlpha, toHex } from "../../../../../helpers";
import { CHART_AXIS_CHOICES } from "../../../../../helpers/figures/charts";
import {
ChartWithDataSetDefinition,
Color,
DispatchResult,
SpreadsheetChildEnv,
TrendConfiguration,
UID,
} from "../../../../../types";
import { Checkbox } from "../../../components/checkbox/checkbox";
import { RadioSelection } from "../../../components/radio_selection/radio_selection";
import { RoundColorPicker } from "../../../components/round_color_picker/round_color_picker";
import { Section } from "../../../components/section/section";
import { SeriesDesignEditor } from "./series_design_editor";

interface Props {
figureId: UID;
definition: ChartWithDataSetDefinition;
canUpdateChart: (
figureID: UID,
definition: Partial<ChartWithDataSetDefinition>
) => DispatchResult;
updateChart: (figureId: UID, definition: Partial<ChartWithDataSetDefinition>) => DispatchResult;
}

export class SeriesWithAxisDesignEditor extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-SeriesWithAxisDesignEditor";
static components = {
SeriesDesignEditor,
Checkbox,
RadioSelection,
Section,
RoundColorPicker,
};
static props = {
figureId: String,
definition: Object,
canUpdateChart: Function,
updateChart: Function,
slots: { type: Object, optional: true },
};

axisChoices = CHART_AXIS_CHOICES;

updateDataSeriesAxis(index: number, axis: "left" | "right") {
const dataSets = [...this.props.definition.dataSets];
if (!dataSets?.[index]) {
return;
}
dataSets[index] = {
...dataSets[index],
yAxisId: axis === "left" ? "y" : "y1",
};
this.props.updateChart(this.props.figureId, { dataSets });
}

getDataSerieAxis(index: number) {
const dataSets = this.props.definition.dataSets;
if (!dataSets?.[index]) {
return "left";
}
return dataSets[index].yAxisId === "y1" ? "right" : "left";
}

get canHaveTwoVerticalAxis() {
return !("horizontal" in this.props.definition && this.props.definition.horizontal);
}

toggleDataTrend(index: number, display: boolean) {
const dataSets = [...this.props.definition.dataSets];
if (!dataSets?.[index]) {
return;
}
dataSets[index] = {
...dataSets[index],
trend: {
type: "polynomial",
order: 1,
...dataSets[index].trend,
display,
},
};
this.props.updateChart(this.props.figureId, { dataSets });
}

getTrendLineConfiguration(index: number) {
const dataSets = this.props.definition.dataSets;
return dataSets?.[index]?.trend;
}

getTrendType(config: TrendConfiguration) {
if (!config) {
return "";
}
return config.type === "polynomial" && config.order === 1 ? "linear" : config.type;
}

onChangeTrendType(index, ev: InputEvent) {
const type = (ev.target as HTMLInputElement).value;
let config: TrendConfiguration;
switch (type) {
case "linear":
case "polynomial":
config = {
type: "polynomial",
order: type === "linear" ? 1 : 2,
};
break;
case "exponential":
case "logarithmic":
config = { type };
break;
default:
return;
}
this.updateTrendLineValue(index, config);
}

onChangePolynomialDegree(index: number, ev: InputEvent) {
const element = ev.target as HTMLInputElement;
const order = parseInt(element.value || "1");
if (order < 2) {
element.value = `${this.getTrendLineConfiguration(index)?.order ?? 2}`;
return;
}
this.updateTrendLineValue(index, { order });
}

getDataSerieColor(index: number) {
const dataSets = this.props.definition.dataSets;
if (!dataSets?.[index]) return "";
const color = dataSets[index].backgroundColor;
return color
? toHex(color)
: getNthColor(index, getColorsPalette(this.props.definition.dataSets.length));
}

getTrendLineColor(index: number) {
return (
this.getTrendLineConfiguration(index)?.color ??
setColorAlpha(this.getDataSerieColor(index), 0.5)
);
}

updateTrendLineColor(index: number, color: Color) {
this.updateTrendLineValue(index, { color });
}

updateTrendLineValue(index: number, config: any) {
const dataSets = [...this.props.definition.dataSets];
if (!dataSets?.[index]) {
return;
}
dataSets[index] = {
...dataSets[index],
trend: {
...dataSets[index].trend,
...config,
},
};
this.props.updateChart(this.props.figureId, { dataSets });
}
}
Loading

0 comments on commit 1e10d97

Please sign in to comment.