PromucFlow_constructor/app/client/src/components/designSystems/appsmith/ChartComponent.tsx
2020-12-24 10:02:25 +05:30

283 lines
7.2 KiB
TypeScript

import _ from "lodash";
import React from "react";
import styled from "styled-components";
import { invisible } from "constants/DefaultTheme";
import { getAppsmithConfigs } from "configs";
import { ChartType, ChartData, ChartDataPoint } from "widgets/ChartWidget";
const FusionCharts = require("fusioncharts");
const Charts = require("fusioncharts/fusioncharts.charts");
const FusionTheme = require("fusioncharts/themes/fusioncharts.theme.fusion");
const { fusioncharts } = getAppsmithConfigs();
Charts(FusionCharts);
FusionTheme(FusionCharts);
FusionCharts.options.license({
key: fusioncharts.licenseKey,
creditLabel: false,
});
export interface ChartComponentProps {
chartType: ChartType;
chartData: ChartData[];
xAxisName: string;
yAxisName: string;
chartName: string;
widgetId: string;
isVisible?: boolean;
allowHorizontalScroll: boolean;
}
const CanvasContainer = styled.div<ChartComponentProps>`
border: none;
border-radius: ${(props) => `${props.theme.radii[1]}px`};
height: 100%;
width: 100%;
background: white;
box-shadow: 0 1px 1px 0 rgba(60,75,100,.14),0 2px 1px -1px rgba(60,75,100,.12),0 1px 3px 0 rgba(60,75,100,.2);
position: relative;
${(props) => (!props.isVisible ? invisible : "")};
padding: 10px 0 0 0;
}`;
class ChartComponent extends React.Component<ChartComponentProps> {
chartInstance = new FusionCharts();
getChartType = () => {
const { chartType, allowHorizontalScroll, chartData } = this.props;
const isMSChart = chartData.length > 1;
switch (chartType) {
case "PIE_CHART":
return "pie2d";
case "LINE_CHART":
return allowHorizontalScroll
? "scrollline2d"
: isMSChart
? "msline"
: "line";
case "BAR_CHART":
return allowHorizontalScroll
? "scrollBar2D"
: isMSChart
? "msbar2d"
: "bar2d";
case "COLUMN_CHART":
return allowHorizontalScroll
? "scrollColumn2D"
: isMSChart
? "mscolumn2d"
: "column2d";
case "AREA_CHART":
return allowHorizontalScroll
? "scrollarea2d"
: isMSChart
? "msarea"
: "area2d";
default:
return allowHorizontalScroll ? "scrollColumn2D" : "mscolumn2d";
}
};
getChartData = () => {
const chartData: ChartData[] = this.props.chartData;
if (chartData.length === 0) {
return [
{
label: "",
value: "",
},
];
}
const data: ChartDataPoint[] = chartData[0].data;
if (data.length === 0) {
return [
{
label: "",
value: "",
},
];
}
return data.map((item) => {
return {
label: item.x,
value: item.y,
};
});
};
getChartCategoriesMutliSeries = (chartData: ChartData[]) => {
const categories: string[] = [];
for (let index = 0; index < chartData.length; index++) {
const data: ChartDataPoint[] = chartData[index].data;
for (let dataIndex = 0; dataIndex < data.length; dataIndex++) {
const category = data[dataIndex].x;
if (!categories.includes(category)) {
categories.push(category);
}
}
}
return categories;
};
getChartCategories = (chartData: ChartData[]) => {
const categories: string[] = this.getChartCategoriesMutliSeries(chartData);
if (categories.length === 0) {
return {
label: "",
};
}
return categories.map((item) => {
return {
label: item,
};
});
};
getSeriesChartData = (data: ChartDataPoint[], categories: string[]) => {
const dataMap: { [key: string]: string } = {};
if (data.length === 0) {
return [
{
value: "",
},
];
}
for (let index = 0; index < data.length; index++) {
const item: ChartDataPoint = data[index];
dataMap[item.x] = item.y;
}
return categories.map((category: string) => {
return {
value: dataMap[category] ? dataMap[category] : null,
};
});
};
getChartDataset = (chartData: ChartData[]) => {
const categories: string[] = this.getChartCategoriesMutliSeries(chartData);
return chartData.map((item: ChartData) => {
const seriesChartData: Array<Record<
string,
unknown
>> = this.getSeriesChartData(item.data, categories);
return {
seriesName: item.seriesName,
data: seriesChartData,
};
});
};
getChartConfig = () => {
return {
caption: this.props.chartName,
xAxisName: this.props.xAxisName,
yAxisName: this.props.yAxisName,
theme: "fusion",
captionAlignment: "left",
captionHorizontalPadding: 10,
alignCaptionWithCanvas: 0,
};
};
getChartDataSource = () => {
if (
this.props.chartData.length <= 1 ||
this.props.chartType === "PIE_CHART"
) {
return {
chart: this.getChartConfig(),
data: this.getChartData(),
};
} else {
return {
chart: this.getChartConfig(),
categories: [
{
category: this.getChartCategories(this.props.chartData),
},
],
dataset: this.getChartDataset(this.props.chartData),
};
}
};
getScrollChartDataSource = () => {
const chartConfig = this.getChartConfig();
return {
chart: {
...chartConfig,
scrollheight: "10",
showvalues: "1",
numVisiblePlot: "5",
flatScrollBars: "1",
},
categories: [
{
category: this.getChartCategories(this.props.chartData),
},
],
dataset: this.getChartDataset(this.props.chartData),
};
};
createGraph = () => {
const dataSource =
this.props.allowHorizontalScroll && this.props.chartType !== "PIE_CHART"
? this.getScrollChartDataSource()
: this.getChartDataSource();
const chartConfig = {
type: this.getChartType(),
renderAt: this.props.widgetId + "chart-container",
width: "100%",
height: "100%",
dataFormat: "json",
dataSource: dataSource,
};
this.chartInstance = new FusionCharts(chartConfig);
};
componentDidMount() {
this.createGraph();
FusionCharts.ready(() => {
/* Component could be unmounted before FusionCharts is ready,
this check ensure we don't render on unmounted component */
if (this.chartInstance) {
this.chartInstance.render();
}
});
}
componentWillUnmount() {
if (this.chartInstance) {
this.chartInstance = null;
}
}
componentDidUpdate(prevProps: ChartComponentProps) {
if (!_.isEqual(prevProps, this.props)) {
const chartType = this.getChartType();
this.chartInstance.chartType(chartType);
if (
this.props.allowHorizontalScroll &&
this.props.chartType !== "PIE_CHART"
) {
this.chartInstance.setChartData(this.getScrollChartDataSource());
} else {
this.chartInstance.setChartData(this.getChartDataSource());
}
}
}
render() {
return (
<CanvasContainer
{...this.props}
id={this.props.widgetId + "chart-container"}
/>
);
}
}
export default ChartComponent;