Skip to content

Commit f97d1c3

Browse files
authored
feat(react-charting): add plotly adapter for grouped vertical bar chart (#33383)
1 parent b9cac91 commit f97d1c3

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Add grouped vertical bar chart plotly adapter",
4+
"packageName": "@fluentui/react-charting",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/charts/react-charting/src/components/DeclarativeChart/DeclarativeChart.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,23 @@ import { DonutChart } from '../DonutChart/index';
55
import { VerticalStackedBarChart } from '../VerticalStackedBarChart/index';
66
import {
77
transformPlotlyJsonToDonutProps,
8-
transformPlotlyJsonToColumnProps,
8+
transformPlotlyJsonToVSBCProps,
99
transformPlotlyJsonToScatterChartProps,
1010
transformPlotlyJsonToHorizontalBarWithAxisProps,
1111
isDateArray,
1212
isNumberArray,
1313
transformPlotlyJsonToHeatmapProps,
1414
transformPlotlyJsonToSankeyProps,
1515
transformPlotlyJsonToGaugeProps,
16+
transformPlotlyJsonToGVBCProps,
1617
} from './PlotlySchemaAdapter';
1718
import { LineChart } from '../LineChart/index';
1819
import { HorizontalBarChartWithAxis } from '../HorizontalBarChartWithAxis/index';
1920
import { AreaChart } from '../AreaChart/index';
2021
import { HeatMapChart } from '../HeatMapChart/index';
2122
import { SankeyChart } from '../SankeyChart/SankeyChart';
2223
import { GaugeChart } from '../GaugeChart/index';
24+
import { GroupedVerticalBarChart } from '../GroupedVerticalBarChart/index';
2325

2426
export interface Schema {
2527
/**
@@ -83,7 +85,10 @@ export const DeclarativeChart: React.FunctionComponent<DeclarativeChartProps> =
8385
<HorizontalBarChartWithAxis {...transformPlotlyJsonToHorizontalBarWithAxisProps(plotlySchema, colorMap)} />
8486
);
8587
} else {
86-
return <VerticalStackedBarChart {...transformPlotlyJsonToColumnProps(plotlySchema, colorMap)} />;
88+
if (['group', 'overlay'].includes(plotlySchema?.layout?.barmode)) {
89+
return <GroupedVerticalBarChart {...transformPlotlyJsonToGVBCProps(plotlySchema, colorMap)} />;
90+
}
91+
return <VerticalStackedBarChart {...transformPlotlyJsonToVSBCProps(plotlySchema, colorMap)} />;
8792
}
8893
case 'scatter':
8994
const isAreaChart = plotlySchema.data.some((series: any) => series.fill === 'tonexty');
@@ -93,7 +98,7 @@ export const DeclarativeChart: React.FunctionComponent<DeclarativeChartProps> =
9398
}
9499
return <LineChart {...transformPlotlyJsonToScatterChartProps(plotlySchema, false, colorMap)} />;
95100
}
96-
return <VerticalStackedBarChart {...transformPlotlyJsonToColumnProps(plotlySchema, colorMap)} />;
101+
return <VerticalStackedBarChart {...transformPlotlyJsonToVSBCProps(plotlySchema, colorMap)} />;
97102
case 'heatmap':
98103
return <HeatMapChart {...transformPlotlyJsonToHeatmapProps(plotlySchema)} />;
99104
case 'sankey':

packages/charts/react-charting/src/components/DeclarativeChart/PlotlySchemaAdapter.ts

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
IVerticalStackedChartProps,
1414
IHeatMapChartData,
1515
IHeatMapChartDataPoint,
16+
IGroupedVerticalBarChartData,
1617
} from '../../types/IDataPoint';
1718
import { ISankeyChartProps } from '../SankeyChart/index';
1819
import { IVerticalStackedBarChartProps } from '../VerticalStackedBarChart/index';
@@ -22,6 +23,7 @@ import { IAreaChartProps } from '../AreaChart/index';
2223
import { IHeatMapChartProps } from '../HeatMapChart/index';
2324
import { getNextColor } from '../../utilities/colors';
2425
import { IGaugeChartProps, IGaugeChartSegment } from '../GaugeChart/index';
26+
import { IGroupedVerticalBarChartProps } from '../GroupedVerticalBarChart/index';
2527

2628
const isDate = (value: any): boolean => !isNaN(Date.parse(value));
2729
const isNumber = (value: any): boolean => !isNaN(parseFloat(value)) && isFinite(value);
@@ -90,7 +92,7 @@ export const transformPlotlyJsonToDonutProps = (
9092
};
9193
};
9294

93-
export const transformPlotlyJsonToColumnProps = (
95+
export const transformPlotlyJsonToVSBCProps = (
9496
jsonObj: any,
9597
colorMap: React.MutableRefObject<Map<string, string>>,
9698
): IVerticalStackedBarChartProps => {
@@ -99,40 +101,77 @@ export const transformPlotlyJsonToColumnProps = (
99101
let yMaxValue = 0;
100102

101103
data.forEach((series: any, index1: number) => {
102-
series.x.forEach((x: string | number, index2: number) => {
104+
series.x?.forEach((x: string | number, index2: number) => {
103105
if (!mapXToDataPoints[x]) {
104106
mapXToDataPoints[x] = { xAxisPoint: x, chartData: [], lineData: [] };
105107
}
106-
const legend = series.name || `Series ${index1 + 1}`;
108+
const legend: string = series.name || `Series ${index1 + 1}`;
107109
if (series.type === 'bar') {
108110
const color = getColor(legend, colorMap);
109111
mapXToDataPoints[x].chartData.push({
110112
legend,
111-
data: series.y[index2],
113+
data: series.y?.[index2],
112114
color,
113115
});
114116
} else if (series.type === 'line') {
115117
const color = getColor(legend, colorMap);
116118
mapXToDataPoints[x].lineData!.push({
117119
legend,
118-
y: series.y[index2],
120+
y: series.y?.[index2],
119121
color,
120122
});
121123
}
122-
yMaxValue = Math.max(yMaxValue, series.y[index2]);
124+
125+
yMaxValue = Math.max(yMaxValue, series.y?.[index2]);
123126
});
124127
});
125128

126129
return {
127130
data: Object.values(mapXToDataPoints),
128-
chartTitle: layout.title,
129-
// width: layout.width,
130-
// height: layout.height,
131+
chartTitle: layout?.title,
132+
// width: layout?.width,
133+
// height: layout?.height,
131134
barWidth: 'auto',
132135
yMaxValue,
133136
};
134137
};
135138

139+
// TODO: Add support for continuous x-axis in grouped vertical bar chart
140+
export const transformPlotlyJsonToGVBCProps = (
141+
jsonObj: any,
142+
colorMap: React.MutableRefObject<Map<string, string>>,
143+
): IGroupedVerticalBarChartProps => {
144+
const { data, layout } = jsonObj;
145+
const mapXToDataPoints: Record<string, IGroupedVerticalBarChartData> = {};
146+
147+
data.forEach((series: any, index1: number) => {
148+
series.x?.forEach((x: string | number, index2: number) => {
149+
if (!mapXToDataPoints[x]) {
150+
mapXToDataPoints[x] = { name: x.toString(), series: [] };
151+
}
152+
if (series.type === 'bar') {
153+
const legend: string = series.name || `Series ${index1 + 1}`;
154+
const color = getColor(legend, colorMap);
155+
156+
mapXToDataPoints[x].series.push({
157+
key: legend,
158+
data: series.y?.[index2],
159+
color,
160+
legend,
161+
});
162+
}
163+
});
164+
});
165+
166+
return {
167+
data: Object.values(mapXToDataPoints),
168+
chartTitle: layout?.title,
169+
// width: layout?.width,
170+
// height: layout?.height,
171+
barwidth: 'auto',
172+
};
173+
};
174+
136175
export const transformPlotlyJsonToScatterChartProps = (
137176
jsonObj: any,
138177
isAreaChart: boolean,

0 commit comments

Comments
 (0)