Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Charts using Plotly schema data #33314

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/charts/react-charting/etc/react-charting.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ export type ChartDataMode = 'default' | 'fraction' | 'percentage';
// @public (undocumented)
Copy link
Collaborator

@fabricteam fabricteam Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕵🏾‍♀️ visual regressions to review in the fluentuiv8 Visual Regression Report

Callout 5 screenshots
Image Name Diff(in Pixels) Image Type
Callout.Beak 25.chromium.png 2186 Changed
Callout.No beak.chromium.png 2306 Changed
Callout.Left bottom edge.chromium.png 3022 Changed
Callout.No callout width specified.chromium.png 2319 Changed
Callout.Right bottom edge.chromium.png 3005 Changed
react-charting-AreaChart 1 screenshots
Image Name Diff(in Pixels) Image Type
react-charting-AreaChart.Custom Accessibility.chromium.png 11 Changed
react-charting-LineChart 1 screenshots
Image Name Diff(in Pixels) Image Type
react-charting-LineChart.Gaps.chromium.png 1 Changed
react-charting-VerticalBarChart 1 screenshots
Image Name Diff(in Pixels) Image Type
react-charting-VerticalBarChart.Basic - Secondary Y Axis.chromium.png 4 Changed

export const ChartHoverCard: React_2.FunctionComponent<IChartHoverCardProps>;

// Warning: (ae-forgotten-export) The symbol "IPlotlySchemaHBC" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export function convertPlotlyToHorizontalBarChartProps(plotlyData: IPlotlySchemaHBC): IChartProps[];
// Warning: (ae-forgotten-export) The symbol "IPlotlySchema" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export function convertPlotlyToILineChartProps(plotlySchema: IPlotlySchema): ILineChartProps;

// @public (undocumented)
export const DataVizGradientPalette: {
gradient1: string;
Expand Down Expand Up @@ -1589,6 +1598,9 @@ export enum NodesComposition {
// @public
export const PieChart: React_2.FunctionComponent<IPieChartProps>;

// @public (undocumented)
export const renderChartFromPlotlyJson: (obj: any) => React_2.ReactNode;

// @public
export const SankeyChart: React_2.FunctionComponent<ISankeyChartProps>;

Expand Down
2 changes: 2 additions & 0 deletions packages/charts/react-charting/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,7 @@ export { DataVizPalette, getColorFromToken, getNextColor } from './utilities/col
export { DataVizGradientPalette, getGradientFromToken, getNextGradient } from './utilities/gradients';
export type { IGaugeChartProps, IGaugeChartSegment, IGaugeChartStyleProps, IGaugeChartStyles } from './GaugeChart';
export { GaugeChart, GaugeChartVariant, GaugeValueFormat } from './GaugeChart';
export { convertPlotlyToILineChartProps, convertPlotlyToHorizontalBarChartProps } from './plotly-utils';
export { renderChartFromPlotlyJson } from './utilities/helpers';

import './version';
100 changes: 100 additions & 0 deletions packages/charts/react-charting/src/plotly-utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { IChartProps } from './index';
import { ILineChartProps } from './LineChart';

interface IPlotlySchema {
data: Array<{
type: string;
mode: string;
name: string;
x: Array<number | string | Date>;
y: Array<number>;
line: {
color: string;
width: number;
dash: string;
};
marker: {
opacity: number;
};
connectgaps: boolean;
}>;
layout: {
title: string;
xaxis: {
title: string;
};
yaxis: {
title: string;
};
};
}

export function convertPlotlyToILineChartProps(plotlySchema: IPlotlySchema): ILineChartProps {
const { data, layout } = plotlySchema;

const lineChartData = data.map(d => ({
legend: d.name,
color: d.line.color,
data: d.x
.filter((x): x is number | Date => typeof x !== 'string')
.map((x, index) => ({
x,
y: d.y[index],
})),
styles: {
legend: d.name,
color: d.line.color,
width: d.line.width,
dash: d.line.dash,
opacity: d.marker.opacity,
},
}));

return {
data: {
chartTitle: layout.title,
lineChartData,
},
};
}

export interface IPlotlySchemaHBC {
data: Array<{
type: string;
orientation: string;
x: number[];
y: string[];
hovertext: string[];
marker: {
color: string[];
};
}>;
layout: {
title: string;
xaxis: {
title: string;
};
yaxis: {
title: string;
};
};
}

export function convertPlotlyToHorizontalBarChartProps(plotlyData: IPlotlySchemaHBC): IChartProps[] {
return plotlyData.data[0].y.map((title: string, index: number) => {
const [xAxisCalloutData, yAxisCalloutData] = plotlyData.data[0].hovertext[index].split(', ');

return {
chartTitle: title,
chartData: [
{
legend: title,
horizontalBarChartdata: { x: plotlyData.data[0].x[index], y: 15000 },
color: plotlyData.data[0].marker.color[index],
xAxisCalloutData,
yAxisCalloutData,
},
],
};
});
}
78 changes: 78 additions & 0 deletions packages/charts/react-charting/src/utilities/helpers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as React from 'react';
import { DonutChart, IDonutChartProps } from '../components/DonutChart/index';
import { IChartProps, IVerticalStackedChartProps } from '../types/IDataPoint';
import { getNextColor } from './colors';
import { IVerticalStackedBarChartProps, VerticalStackedBarChart } from '../components/VerticalStackedBarChart/index';

const transformPlotlyJsonToDonutProps = (obj: any): IDonutChartProps => {
const donutData: IChartProps = {
chartTitle: obj.layout.title,
chartData: obj.data[0].labels.map((label: string, index: number) => {
return {
legend: label,
data: obj.data[0].values[index],
color: obj.data[0].marker?.color || getNextColor(index),
};
}),
};

// const width: number = obj.layout.width;
// const height: number = obj.layout.height;
// const innerRadius: number = (Math.min(width, height) * obj.data[0].hole) / 2;

return {
data: donutData,
hideLegend: !obj.layout.showlegend,
// width,
// height,
// innerRadius,
};
};

const transformPlotlyJsonToColumnProps = (obj: any): IVerticalStackedBarChartProps => {
const mapXToDataPoints: { [key: string]: IVerticalStackedChartProps } = {};
let yMaxValue = 0;

obj.data.forEach((series: any, index1: number) => {
series.x.forEach((x: string | number, index2: number) => {
if (!mapXToDataPoints[x]) {
mapXToDataPoints[x] = { xAxisPoint: x, chartData: [], lineData: [] };
}
if (series.type === 'bar') {
mapXToDataPoints[x].chartData.push({
legend: series.name,
data: series.y[index2],
color: series.marker?.color || getNextColor(index1),
});
} else if (series.type === 'line') {
mapXToDataPoints[x].lineData!.push({
legend: series.name,
y: series.y[index2],
color: series.marker?.color || getNextColor(index1),
});
}
yMaxValue = Math.max(yMaxValue, series.y[index2]);
});
});

return {
data: Object.values(mapXToDataPoints),
chartTitle: obj.layout.title,
// width: obj.layout.width,
// height: obj.layout.height,
barWidth: 'auto',
yMaxValue,
};
};

export const renderChartFromPlotlyJson = (obj: any): React.ReactNode => {
switch (obj.data[0].type) {
case 'pie':
return <DonutChart {...transformPlotlyJsonToDonutProps(obj)} />;
case 'bar':
return <VerticalStackedBarChart {...transformPlotlyJsonToColumnProps(obj)} />;
default:
return null;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import { renderChartFromPlotlyJson } from '@fluentui/react-charting';

const plotlyJson = {
data: [
{
hole: 0.6,
type: 'pie',
labels: ['Rural', 'Suburban', 'Urban'],
values: [125, 625, 1625],
},
],
layout: {
title: 'Donut w Ply',
showlegend: false,
},
};

export class DonutChartPlotlyExample extends React.Component<{}, {}> {
public render(): React.ReactNode {
return renderChartFromPlotlyJson(plotlyJson);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DonutChartBasicExample } from './DonutChart.Basic.Example';
import { DonutChartDynamicExample } from './DonutChart.Dynamic.Example';
import { DonutChartCustomCalloutExample } from './DonutChart.CustomCallout.Example';
import { DonutChartCustomAccessibilityExample } from './DonutChart.CustomAccessibility.Example';
import { DonutChartPlotlyExample } from './DonutChart.Plotly.Example';

const DonutChartBasicExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.Basic.Example.tsx') as string;
Expand All @@ -15,6 +16,8 @@ const DonutChartCustomCalloutExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.CustomCallout.Example.tsx') as string;
const DonutChartCustomAccessibilityExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.CustomAccessibility.Example.tsx') as string;
const DonutChartPlotlyExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.Plotly.Example.tsx') as string;

export const DonutChartPageProps: IDocPageProps = {
title: 'DonutChart',
Expand Down Expand Up @@ -42,6 +45,11 @@ export const DonutChartPageProps: IDocPageProps = {
code: DonutChartCustomAccessibilityExampleCode,
view: <DonutChartCustomAccessibilityExample />,
},
{
title: 'DonutChart Plotly',
code: DonutChartPlotlyExampleCode,
view: <DonutChartPlotlyExample />,
},
],
overview: require<string>('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/docs/DonutChartOverview.md'),
bestPractices: require<string>('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/docs/DonutChartBestPractices.md'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { DonutChartBasicExample } from './DonutChart.Basic.Example';
import { DonutChartDynamicExample } from './DonutChart.Dynamic.Example';
import { DonutChartCustomCalloutExample } from './DonutChart.CustomCallout.Example';
import { DonutChartCustomAccessibilityExample } from './DonutChart.CustomAccessibility.Example';
import { DonutChartPlotlyExample } from './DonutChart.Plotly.Example';

const DonutChartBasicExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.Basic.Example.tsx') as string;
Expand All @@ -21,6 +22,8 @@ const DonutChartCustomCalloutExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.CustomCallout.Example.tsx') as string;
const DonutChartCustomAccessibilityExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.CustomAccessibility.Example.tsx') as string;
const DonutChartPlotlyExampleCode =
require('!raw-loader?esModule=false!@fluentui/react-examples/src/react-charting/DonutChart/DonutChart.Plotly.Example.tsx') as string;

export class DonutChartPage extends React.Component<IComponentDemoPageProps, {}> {
public render(): JSX.Element {
Expand All @@ -42,6 +45,9 @@ export class DonutChartPage extends React.Component<IComponentDemoPageProps, {}>
<ExampleCard title="DonutChart Custom Accessibility" code={DonutChartCustomAccessibilityExampleCode}>
<DonutChartCustomAccessibilityExample />
</ExampleCard>
<ExampleCard title="DonutChart Plotly" code={DonutChartPlotlyExampleCode}>
<DonutChartPlotlyExample />
</ExampleCard>
</div>
}
propertiesTables={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DonutChartBasicExample } from './DonutChart.Basic.Example';
import { DonutChartCustomAccessibilityExample } from './DonutChart.CustomAccessibility.Example';
import { DonutChartCustomCalloutExample } from './DonutChart.CustomCallout.Example';
import { DonutChartDynamicExample } from './DonutChart.Dynamic.Example';
import { DonutChartPlotlyExample } from './DonutChart.Plotly.Example';

export const Basic = () => <DonutChartBasicExample />;

Expand All @@ -13,6 +14,8 @@ export const CustomCallout = () => <DonutChartCustomCalloutExample />;

export const Dynamic = () => <DonutChartDynamicExample />;

export const Plotly = () => <DonutChartPlotlyExample />;

export default {
title: 'Components/DonutChart',
};
Loading
Loading