Skip to content

Commit 002f3d9

Browse files
Anush2303Anush
andauthored
fix(charts): fix chart exception issue (#35342)
Co-authored-by: Anush <anushgupta@microsoft.com>
1 parent befc650 commit 002f3d9

File tree

6 files changed

+150
-34
lines changed

6 files changed

+150
-34
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": "fix chart exception issue",
4+
"packageName": "@fluentui/react-charting",
5+
"email": "anushgupta@microsoft.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "fix chart exception issue",
4+
"packageName": "@fluentui/react-charts",
5+
"email": "anushgupta@microsoft.com",
6+
"dependentChangeType": "patch"
7+
}

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

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -703,42 +703,43 @@ export const transformPlotlyJsonToVSBCProps = (
703703
.filter(shape => shape.type === 'line')
704704
.forEach((shape, shapeIdx) => {
705705
const lineColor = shape.line?.color;
706-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
707-
const resolveX = (val: any) => {
706+
const resolveX = (val: Datum) => {
708707
if (typeof val === 'number' && Array.isArray(xCategories) && xCategories[val] !== undefined) {
709708
return xCategories[val];
710709
}
711710
return val;
712711
};
713712

714-
const x0Key = resolveX(shape.x0);
715-
const x1Key = resolveX(shape.x1);
716-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
717-
const resolveY = (val: any) => {
713+
const x0Key = resolveX(shape.x0!);
714+
const x1Key = resolveX(shape.x1!);
715+
const resolveY = (val: Datum) => {
718716
if (shape.yref === 'paper') {
719717
if (val === 0) {
720718
return yMinValue;
721719
}
722720
if (val === 1) {
723721
return yMaxValue;
724722
}
725-
return yMinValue + val * (yMaxValue - yMinValue);
723+
if (typeof val === 'number') {
724+
return yMinValue + val * (yMaxValue - yMinValue);
725+
}
726+
return val;
726727
}
727728
return val;
728729
};
729730

730-
const y0Val = resolveY(shape.y0);
731-
const y1Val = resolveY(shape.y1);
732-
mapXToDataPoints[x0Key].lineData!.push({
731+
const y0Val = resolveY(shape.y0!);
732+
const y1Val = resolveY(shape.y1!);
733+
mapXToDataPoints[x0Key as string].lineData!.push({
733734
legend: `Reference_${shapeIdx}`,
734-
y: y0Val,
735+
y: y0Val as string,
735736
color: rgb(lineColor!).formatHex8() ?? lineColor,
736737
lineOptions: getLineOptions(shape.line),
737738
useSecondaryYScale: false,
738739
});
739-
mapXToDataPoints[x1Key].lineData!.push({
740+
mapXToDataPoints[x1Key as string].lineData!.push({
740741
legend: `Reference_${shapeIdx}`,
741-
y: y1Val,
742+
y: y1Val as string,
742743
color: rgb(lineColor!).formatHex8() ?? lineColor,
743744
lineOptions: getLineOptions(shape.line),
744745
useSecondaryYScale: false,
@@ -1102,7 +1103,6 @@ export const transformPlotlyJsonToScatterChartProps = (
11021103
) as IScatterChartProps;
11031104
};
11041105

1105-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
11061106
const mapColorFillBars = (layout: Partial<Layout> | undefined) => {
11071107
if (!Array.isArray(layout?.shapes)) {
11081108
return [];
@@ -1236,16 +1236,51 @@ const transformPlotlyJsonToScatterTraceProps = (
12361236
})
12371237
.flat();
12381238

1239+
const xMinValue = chartData[0]?.data[0]?.x;
1240+
const xMaxValue = chartData[0]?.data[chartData[0].data.length - 1]?.x;
1241+
const yMinValue = chartData[0]?.data[0]?.y;
1242+
const yMaxValue = chartData[0]?.data[chartData[0].data.length - 1]?.y;
12391243
const lineShape: ILineChartPoints[] = (input.layout?.shapes ?? [])
12401244
.filter(shape => shape.type === 'line')
12411245
.map((shape, shapeIdx) => {
12421246
const lineColor = shape.line?.color;
12431247

1248+
const resolveX = (val: Datum) => {
1249+
if (shape.xref === 'paper') {
1250+
if (val === 0) {
1251+
return xMinValue;
1252+
}
1253+
if (val === 1) {
1254+
return xMaxValue;
1255+
}
1256+
return typeof xMinValue === 'number' && typeof xMaxValue === 'number' && typeof val === 'number'
1257+
? xMinValue + val * (xMaxValue - xMinValue)
1258+
: val;
1259+
}
1260+
return val;
1261+
};
1262+
1263+
const resolveY = (val: Datum) => {
1264+
if (shape.yref === 'paper') {
1265+
if (val === 0) {
1266+
return yMinValue;
1267+
}
1268+
if (val === 1) {
1269+
return yMaxValue;
1270+
}
1271+
if (typeof val === 'number') {
1272+
return yMinValue + val * (yMaxValue - yMinValue);
1273+
}
1274+
return val;
1275+
}
1276+
return val;
1277+
};
1278+
12441279
return {
12451280
legend: `Reference_${shapeIdx}`,
12461281
data: [
1247-
{ x: shape.x0, y: shape.y0 },
1248-
{ x: shape.x1, y: shape.y1 },
1282+
{ x: resolveX(shape.x0!), y: resolveY(shape.y0!) },
1283+
{ x: resolveX(shape.x1!), y: resolveY(shape.y1!) },
12491284
],
12501285
color: rgb(lineColor!).formatHex8() ?? lineColor,
12511286
lineOptions: getLineOptions(shape.line),
@@ -1306,9 +1341,11 @@ const transformPlotlyJsonToScatterTraceProps = (
13061341
...getAxisCategoryOrderProps(input.data, input.layout),
13071342
}
13081343
: {}),
1309-
...(!isScatterChart && mapColorFillBars(input.layout)?.length
1310-
? { colorFillBars: mapColorFillBars(input.layout) }
1311-
: {}),
1344+
...(!isScatterChart &&
1345+
(() => {
1346+
const bars = mapColorFillBars(input.layout);
1347+
return bars && !bars.includes(null) ? { colorFillBars: bars } : {};
1348+
})()),
13121349
} as ILineChartProps | IScatterChartProps;
13131350
}
13141351
};

packages/charts/react-charting/src/components/DeclarativeChart/__snapshots__/PlotlySchemaAdapterUT.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3345,6 +3345,7 @@ Object {
33453345
exports[`transform Plotly Json To chart Props transformPlotlyJsonToLineChartProps - Should return line chart props 1`] = `
33463346
Object {
33473347
"chartTitle": "",
3348+
"colorFillBars": Array [],
33483349
"data": Object {
33493350
"lineChartData": Array [
33503351
Object {

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

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import type {
6666
TraceInfo,
6767
DTickValue,
6868
AxisType,
69+
Shape,
6970
} from '@fluentui/chart-utilities';
7071
import {
7172
isArrayOrTypedArray,
@@ -705,42 +706,43 @@ export const transformPlotlyJsonToVSBCProps = (
705706
.filter(shape => shape.type === 'line')
706707
.forEach((shape, shapeIdx) => {
707708
const lineColor = shape.line?.color;
708-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
709-
const resolveX = (val: any) => {
709+
const resolveX = (val: Datum) => {
710710
if (typeof val === 'number' && Array.isArray(xCategories) && xCategories[val] !== undefined) {
711711
return xCategories[val];
712712
}
713713
return val;
714714
};
715715

716-
const x0Key = resolveX(shape.x0);
717-
const x1Key = resolveX(shape.x1);
718-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
719-
const resolveY = (val: any) => {
716+
const x0Key = resolveX(shape.x0!);
717+
const x1Key = resolveX(shape.x1!);
718+
const resolveY = (val: Datum) => {
720719
if (shape.yref === 'paper') {
721720
if (val === 0) {
722721
return yMinValue;
723722
}
724723
if (val === 1) {
725724
return yMaxValue;
726725
}
727-
return yMinValue + val * (yMaxValue - yMinValue);
726+
if (typeof val === 'number') {
727+
return yMinValue + val * (yMaxValue - yMinValue);
728+
}
729+
return val;
728730
}
729731
return val;
730732
};
731733

732-
const y0Val = resolveY(shape.y0);
733-
const y1Val = resolveY(shape.y1);
734-
mapXToDataPoints[x0Key].lineData!.push({
734+
const y0Val = resolveY(shape.y0!);
735+
const y1Val = resolveY(shape.y1!);
736+
mapXToDataPoints[x0Key as string].lineData!.push({
735737
legend: `Reference_${shapeIdx}`,
736-
y: y0Val,
738+
y: y0Val as string,
737739
color: rgb(lineColor!).formatHex8() ?? lineColor,
738740
lineOptions: getLineOptions(shape.line),
739741
useSecondaryYScale: false,
740742
});
741-
mapXToDataPoints[x1Key].lineData!.push({
743+
mapXToDataPoints[x1Key as string].lineData!.push({
742744
legend: `Reference_${shapeIdx}`,
743-
y: y1Val,
745+
y: y1Val as string,
744746
color: rgb(lineColor!).formatHex8() ?? lineColor,
745747
lineOptions: getLineOptions(shape.line),
746748
useSecondaryYScale: false,
@@ -1101,6 +1103,26 @@ export const transformPlotlyJsonToScatterChartProps = (
11011103
) as ScatterChartProps;
11021104
};
11031105

1106+
const mapColorFillBars = (layout: Partial<Layout> | undefined) => {
1107+
if (!Array.isArray(layout?.shapes)) {
1108+
return [];
1109+
}
1110+
1111+
return layout.shapes
1112+
.filter((shape: Partial<Shape>) => shape.type === 'rect')
1113+
.map((shape: { x0?: Datum; x1?: Datum; fillcolor?: string }) => {
1114+
//colorFillbars doesn't support string dates or categories
1115+
if (typeof shape.x0 === 'string' || typeof shape.x1 === 'string') {
1116+
return null;
1117+
}
1118+
return {
1119+
color: shape.fillcolor!,
1120+
data: [{ startX: shape.x0, endX: shape.x1 }],
1121+
applyPattern: false,
1122+
};
1123+
});
1124+
};
1125+
11041126
const transformPlotlyJsonToScatterTraceProps = (
11051127
input: PlotlySchema,
11061128
isMultiPlot: boolean,
@@ -1213,16 +1235,52 @@ const transformPlotlyJsonToScatterTraceProps = (
12131235
})
12141236
.flat();
12151237

1238+
const xMinValue = chartData[0]?.data[0]?.x;
1239+
const xMaxValue = chartData[0]?.data[chartData[0].data.length - 1]?.x;
1240+
const yMinValue = chartData[0]?.data[0]?.y;
1241+
const yMaxValue = chartData[0]?.data[chartData[0].data.length - 1]?.y;
1242+
12161243
const lineShape: LineChartPoints[] = (input.layout?.shapes ?? [])
12171244
.filter(shape => shape.type === 'line')
12181245
.map((shape, shapeIdx) => {
12191246
const lineColor = shape.line?.color;
1247+
const resolveX = (val: Datum) => {
1248+
if (shape.xref === 'paper') {
1249+
if (val === 0) {
1250+
return xMinValue;
1251+
}
1252+
if (val === 1) {
1253+
return xMaxValue;
1254+
}
1255+
if (typeof val === 'number' && typeof xMinValue === 'number' && typeof xMaxValue === 'number') {
1256+
return xMinValue + val * (xMaxValue - xMinValue);
1257+
}
1258+
return val;
1259+
}
1260+
return val;
1261+
};
1262+
1263+
const resolveY = (val: Datum) => {
1264+
if (shape.yref === 'paper') {
1265+
if (val === 0) {
1266+
return yMinValue;
1267+
}
1268+
if (val === 1) {
1269+
return yMaxValue;
1270+
}
1271+
if (typeof val === 'number') {
1272+
return yMinValue + val * (yMaxValue - yMinValue);
1273+
}
1274+
return val;
1275+
}
1276+
return val;
1277+
};
12201278

12211279
return {
12221280
legend: `Reference_${shapeIdx}`,
12231281
data: [
1224-
{ x: shape.x0, y: shape.y0 },
1225-
{ x: shape.x1, y: shape.y1 },
1282+
{ x: resolveX(shape.x0!), y: resolveY(shape.y0!) },
1283+
{ x: resolveX(shape.x1!), y: resolveY(shape.y1!) },
12261284
],
12271285
color: rgb(lineColor!).formatHex8() ?? lineColor,
12281286
lineOptions: getLineOptions(shape.line),
@@ -1281,6 +1339,11 @@ const transformPlotlyJsonToScatterTraceProps = (
12811339
...getAxisCategoryOrderProps(input.data, input.layout),
12821340
}
12831341
: {}),
1342+
...(!isScatterChart &&
1343+
(() => {
1344+
const bars = mapColorFillBars(input.layout);
1345+
return bars && !bars.includes(null) ? { colorFillBars: bars } : {};
1346+
})()),
12841347
} as LineChartProps;
12851348
}
12861349
};

packages/charts/react-charts/library/src/components/DeclarativeChart/__snapshots__/PlotlySchemaAdapterUT.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3074,6 +3074,7 @@ Object {
30743074
exports[`transform Plotly Json To chart Props transformPlotlyJsonToLineChartProps - Should return line chart props 1`] = `
30753075
Object {
30763076
"chartTitle": "",
3077+
"colorFillBars": Array [],
30773078
"data": Object {
30783079
"lineChartData": Array [
30793080
Object {

0 commit comments

Comments
 (0)