2023-07-28 13:29:16 +00:00
|
|
|
import type { ChartComponentProps } from ".";
|
|
|
|
|
import type { AllChartData } from "../constants";
|
2023-08-03 05:58:49 +00:00
|
|
|
import {
|
|
|
|
|
LabelOrientation,
|
|
|
|
|
type ChartData,
|
|
|
|
|
XAxisCategory,
|
|
|
|
|
messages,
|
|
|
|
|
} from "../constants";
|
2023-07-28 13:29:16 +00:00
|
|
|
|
|
|
|
|
import { Colors } from "constants/Colors";
|
2023-08-18 13:50:39 +00:00
|
|
|
import { EChartsLayoutBuilder } from "./LayoutBuilders/EChartsLayoutBuilder";
|
2023-07-28 13:29:16 +00:00
|
|
|
|
|
|
|
|
export class EChartsConfigurationBuilder {
|
|
|
|
|
fontFamily: string | undefined;
|
|
|
|
|
|
2023-08-14 13:54:05 +00:00
|
|
|
#seriesConfigurationForPieChart(
|
|
|
|
|
seriesID: string,
|
|
|
|
|
seriesData: ChartData,
|
|
|
|
|
showDataPointLabel: boolean,
|
|
|
|
|
) {
|
2023-08-03 05:58:49 +00:00
|
|
|
let seriesName = messages.Undefined;
|
|
|
|
|
if (seriesData.seriesName && seriesData.seriesName.length > 0) {
|
|
|
|
|
seriesName = seriesData.seriesName;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-28 13:29:16 +00:00
|
|
|
const config = {
|
|
|
|
|
type: "pie",
|
2023-08-18 13:50:39 +00:00
|
|
|
radius: "60%",
|
|
|
|
|
center: ["50%", "60%"],
|
2023-08-03 05:58:49 +00:00
|
|
|
name: seriesName,
|
2023-07-28 13:29:16 +00:00
|
|
|
label: {
|
2023-08-14 13:54:05 +00:00
|
|
|
show: showDataPointLabel,
|
2023-07-28 13:29:16 +00:00
|
|
|
fontFamily: this.fontFamily,
|
|
|
|
|
color: Colors.DOVE_GRAY2,
|
2023-08-03 05:58:49 +00:00
|
|
|
formatter: `{b} : {d}%`,
|
2023-07-28 13:29:16 +00:00
|
|
|
},
|
|
|
|
|
encode: {
|
|
|
|
|
itemName: XAxisCategory,
|
|
|
|
|
tooltip: seriesID,
|
|
|
|
|
value: seriesID,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#seriesConfigForChart(
|
|
|
|
|
props: ChartComponentProps,
|
|
|
|
|
allSeriesData: AllChartData,
|
|
|
|
|
) {
|
|
|
|
|
/**
|
|
|
|
|
* {
|
|
|
|
|
* series: [ { type: "pie", radius: "40%", center: ["50%", 50%]}]
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
const configs: unknown[] = [];
|
|
|
|
|
|
|
|
|
|
Object.keys(allSeriesData).forEach((seriesID, index) => {
|
|
|
|
|
const seriesData = allSeriesData[seriesID];
|
|
|
|
|
let color = seriesData.color;
|
|
|
|
|
|
|
|
|
|
if (index == 0 && (!color || color.length == 0)) {
|
|
|
|
|
color = props.primaryColor;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-03 05:58:49 +00:00
|
|
|
let seriesName = messages.Undefined;
|
|
|
|
|
if (seriesData.seriesName && seriesData.seriesName.length > 0) {
|
|
|
|
|
seriesName = seriesData.seriesName;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-28 13:29:16 +00:00
|
|
|
let config: Record<string, unknown> = {
|
2023-08-14 13:54:05 +00:00
|
|
|
label: { show: props.showDataPointLabel, position: "top" },
|
2023-08-03 05:58:49 +00:00
|
|
|
name: seriesName,
|
2023-07-28 13:29:16 +00:00
|
|
|
itemStyle: { color: color },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
switch (props.chartType) {
|
|
|
|
|
case "BAR_CHART":
|
|
|
|
|
config = { ...config, type: "bar" };
|
|
|
|
|
|
|
|
|
|
// The series label should be on the right for bar chart
|
|
|
|
|
(config.label as Record<string, unknown>).position = "right";
|
|
|
|
|
break;
|
|
|
|
|
case "COLUMN_CHART":
|
|
|
|
|
config = { ...config, type: "bar" };
|
|
|
|
|
break;
|
|
|
|
|
case "LINE_CHART":
|
|
|
|
|
config = { ...config, type: "line" };
|
|
|
|
|
break;
|
|
|
|
|
case "AREA_CHART":
|
|
|
|
|
config = {
|
|
|
|
|
...config,
|
|
|
|
|
type: "line",
|
|
|
|
|
areaStyle: {},
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
case "PIE_CHART":
|
2023-08-14 13:54:05 +00:00
|
|
|
config = this.#seriesConfigurationForPieChart(
|
|
|
|
|
seriesID,
|
|
|
|
|
seriesData,
|
|
|
|
|
props.showDataPointLabel,
|
|
|
|
|
);
|
2023-07-28 13:29:16 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configs.push(config);
|
|
|
|
|
});
|
|
|
|
|
return configs;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 13:50:39 +00:00
|
|
|
seriesTitleOffsetForPieChart = (props: ChartComponentProps) => {
|
|
|
|
|
return 0.3 * props.dimensions.componentHeight - 35;
|
|
|
|
|
};
|
|
|
|
|
|
2023-07-28 13:29:16 +00:00
|
|
|
#evaluateFontFamily(fontFamily: string | undefined) {
|
|
|
|
|
return fontFamily === "System Default" ? "inherit" : fontFamily;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 13:50:39 +00:00
|
|
|
#titleConfigForPiechart(
|
|
|
|
|
props: ChartComponentProps,
|
|
|
|
|
allSeriesData: AllChartData,
|
|
|
|
|
) {
|
2023-07-28 13:29:16 +00:00
|
|
|
const config: Record<string, unknown>[] = [];
|
|
|
|
|
const numSeries = Object.keys(allSeriesData).length;
|
|
|
|
|
const interval = 100 / (numSeries + 1);
|
|
|
|
|
|
|
|
|
|
Object.values(allSeriesData).forEach((seriesData, index) => {
|
|
|
|
|
const offset = `${(index + 1) * interval}%`;
|
|
|
|
|
config.push({
|
2023-08-18 13:50:39 +00:00
|
|
|
top: this.seriesTitleOffsetForPieChart(props),
|
2023-07-28 13:29:16 +00:00
|
|
|
left: offset,
|
|
|
|
|
textAlign: "center",
|
|
|
|
|
text: seriesData.seriesName ?? "",
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#titleConfigForChart(
|
|
|
|
|
props: ChartComponentProps,
|
|
|
|
|
allSeriesData: AllChartData,
|
2023-08-18 13:50:39 +00:00
|
|
|
layoutConfig: Record<string, Record<string, unknown>>,
|
2023-07-28 13:29:16 +00:00
|
|
|
) {
|
|
|
|
|
/**
|
|
|
|
|
* title: [
|
|
|
|
|
* {
|
|
|
|
|
* text: "chart title",
|
|
|
|
|
* },
|
|
|
|
|
* // Valid for PIE Chart only
|
|
|
|
|
* {
|
|
|
|
|
*
|
|
|
|
|
* text: "2014",
|
|
|
|
|
* top: "15%",
|
|
|
|
|
* left: "50%",
|
|
|
|
|
* textAlign: "center"
|
|
|
|
|
* }
|
|
|
|
|
* ]
|
|
|
|
|
*/
|
|
|
|
|
const defaultTitleConfig = {
|
|
|
|
|
text: props.chartName,
|
2023-08-18 13:50:39 +00:00
|
|
|
show: layoutConfig.title.show,
|
2023-07-28 13:29:16 +00:00
|
|
|
padding: [5, 50],
|
|
|
|
|
left: "center",
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontFamily: this.fontFamily,
|
|
|
|
|
fontSize: 24,
|
|
|
|
|
color: Colors.THUNDER,
|
|
|
|
|
overflow: "truncate",
|
|
|
|
|
width: props.dimensions.componentWidth - 100,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (props.chartType == "PIE_CHART") {
|
|
|
|
|
return [
|
|
|
|
|
defaultTitleConfig,
|
2023-08-18 13:50:39 +00:00
|
|
|
...this.#titleConfigForPiechart(props, allSeriesData),
|
2023-07-28 13:29:16 +00:00
|
|
|
];
|
|
|
|
|
} else {
|
|
|
|
|
return defaultTitleConfig;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#configForLabelOrientation(props: ChartComponentProps) {
|
2023-08-18 13:50:39 +00:00
|
|
|
switch (props.labelOrientation) {
|
|
|
|
|
case LabelOrientation.SLANT:
|
|
|
|
|
return 45;
|
|
|
|
|
case LabelOrientation.ROTATE:
|
|
|
|
|
return 90;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
2023-07-28 13:29:16 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#defaultEChartConfig = (
|
2023-08-18 13:50:39 +00:00
|
|
|
layoutConfig: Record<string, Record<string, unknown>>,
|
2023-07-28 13:29:16 +00:00
|
|
|
): Record<string, unknown> => {
|
|
|
|
|
const config: Record<string, any> = {
|
|
|
|
|
legend: {
|
2023-08-18 13:50:39 +00:00
|
|
|
show: layoutConfig.legend.show,
|
2023-07-28 13:29:16 +00:00
|
|
|
type: "scroll",
|
|
|
|
|
left: "center",
|
|
|
|
|
align: "left",
|
2023-08-18 13:50:39 +00:00
|
|
|
top: layoutConfig.legend.top,
|
2023-07-28 13:29:16 +00:00
|
|
|
orient: "horizontal",
|
|
|
|
|
textStyle: { fontFamily: this.fontFamily },
|
|
|
|
|
padding: [5, 50],
|
|
|
|
|
},
|
|
|
|
|
tooltip: {
|
|
|
|
|
trigger: "item",
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
config.grid = {
|
2023-08-18 13:50:39 +00:00
|
|
|
top: layoutConfig.grid.top,
|
|
|
|
|
bottom: layoutConfig.grid.bottom,
|
|
|
|
|
left: layoutConfig.grid.left,
|
|
|
|
|
show: false,
|
2023-07-28 13:29:16 +00:00
|
|
|
};
|
|
|
|
|
return config;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-18 13:50:39 +00:00
|
|
|
#yAxisConfig = (
|
|
|
|
|
props: ChartComponentProps,
|
|
|
|
|
layoutConfig: Record<string, Record<string, unknown>>,
|
|
|
|
|
) => {
|
2023-07-28 13:29:16 +00:00
|
|
|
/**
|
|
|
|
|
* {
|
|
|
|
|
* type: "value", name: "Y Axis Name", nameLocation: "end"
|
|
|
|
|
* }
|
|
|
|
|
*/
|
2023-08-18 13:50:39 +00:00
|
|
|
let config: Record<string, unknown> = {
|
|
|
|
|
show: layoutConfig.yAxis.show,
|
|
|
|
|
};
|
|
|
|
|
|
2023-07-28 13:29:16 +00:00
|
|
|
if (props.chartType != "PIE_CHART") {
|
|
|
|
|
config = {
|
2023-08-18 13:50:39 +00:00
|
|
|
...config,
|
2023-07-28 13:29:16 +00:00
|
|
|
name: props.yAxisName,
|
|
|
|
|
nameLocation: "middle",
|
2023-08-18 13:50:39 +00:00
|
|
|
nameGap: layoutConfig.yAxis.nameGap,
|
2023-07-28 13:29:16 +00:00
|
|
|
nameTextStyle: {
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
fontFamily: this.fontFamily,
|
|
|
|
|
color: Colors.DOVE_GRAY2,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (props.chartType == "BAR_CHART") {
|
|
|
|
|
config.type = "category";
|
|
|
|
|
}
|
|
|
|
|
if (props.setAdaptiveYMin) {
|
|
|
|
|
config.min = "dataMin";
|
|
|
|
|
}
|
|
|
|
|
config.axisLabel = {
|
|
|
|
|
fontFamily: this.fontFamily,
|
|
|
|
|
color: Colors.DOVE_GRAY2,
|
2023-08-18 13:50:39 +00:00
|
|
|
show: layoutConfig.yAxis.show,
|
|
|
|
|
width: (layoutConfig.yAxis.axisLabel as Record<string, unknown>).width,
|
|
|
|
|
overflow: "break",
|
2023-07-28 13:29:16 +00:00
|
|
|
};
|
|
|
|
|
return config;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-18 13:50:39 +00:00
|
|
|
#xAxisConfig = (
|
|
|
|
|
props: ChartComponentProps,
|
|
|
|
|
layoutConfig: Record<string, Record<string, unknown>>,
|
|
|
|
|
) => {
|
2023-07-28 13:29:16 +00:00
|
|
|
/**
|
|
|
|
|
* {
|
|
|
|
|
* type: "value", name: "X Axis Name", nameLocation: "end"
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
const config: Record<string, unknown> = {};
|
|
|
|
|
let type = "category";
|
|
|
|
|
if (props.chartType == "BAR_CHART") {
|
|
|
|
|
type = "value";
|
|
|
|
|
}
|
|
|
|
|
config.type = type;
|
2023-08-18 13:50:39 +00:00
|
|
|
config.axisLabel = {
|
|
|
|
|
show: layoutConfig.xAxis.show,
|
|
|
|
|
fontFamily: this.fontFamily,
|
|
|
|
|
color: Colors.DOVE_GRAY2,
|
|
|
|
|
rotate: this.#configForLabelOrientation(props),
|
|
|
|
|
width: (layoutConfig.xAxis.axisLabel as Record<string, unknown>).width,
|
|
|
|
|
overflow: "break",
|
|
|
|
|
};
|
2023-07-28 13:29:16 +00:00
|
|
|
|
|
|
|
|
if (props.chartType == "BAR_CHART" && props.setAdaptiveYMin) {
|
|
|
|
|
config.min = "dataMin";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (props.chartType != "PIE_CHART") {
|
|
|
|
|
config.name = props.xAxisName;
|
|
|
|
|
config.nameLocation = "middle";
|
2023-08-18 13:50:39 +00:00
|
|
|
config.nameGap = layoutConfig.xAxis.nameGap;
|
2023-07-28 13:29:16 +00:00
|
|
|
config.nameTextStyle = {
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
fontFamily: this.fontFamily,
|
|
|
|
|
color: Colors.DOVE_GRAY2,
|
|
|
|
|
};
|
|
|
|
|
}
|
2023-08-18 13:50:39 +00:00
|
|
|
|
|
|
|
|
config.show = layoutConfig.xAxis.show;
|
2023-07-28 13:29:16 +00:00
|
|
|
return config;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-18 13:50:39 +00:00
|
|
|
#scrollConfig = (
|
|
|
|
|
props: ChartComponentProps,
|
|
|
|
|
layoutConfig: Record<string, Record<string, unknown>>,
|
|
|
|
|
) => {
|
2023-07-28 13:29:16 +00:00
|
|
|
if (props.allowScroll) {
|
|
|
|
|
if (props.chartType != "PIE_CHART") {
|
|
|
|
|
return [
|
|
|
|
|
{
|
2023-08-18 13:50:39 +00:00
|
|
|
show: layoutConfig.scrollBar.show,
|
2023-07-28 13:29:16 +00:00
|
|
|
type: "slider",
|
|
|
|
|
filterMode: "filter",
|
|
|
|
|
start: "20",
|
2023-08-18 13:50:39 +00:00
|
|
|
bottom: layoutConfig.scrollBar.bottom,
|
|
|
|
|
height: layoutConfig.scrollBar.height,
|
2023-07-28 13:29:16 +00:00
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
prepareEChartConfig(props: ChartComponentProps, allSeriesData: AllChartData) {
|
2023-08-18 13:50:39 +00:00
|
|
|
const layoutBuilder = new EChartsLayoutBuilder({
|
|
|
|
|
allowScroll: props.allowScroll,
|
|
|
|
|
height: props.dimensions.componentHeight,
|
|
|
|
|
width: props.dimensions.componentWidth,
|
|
|
|
|
labelOrientation: props.labelOrientation ?? LabelOrientation.AUTO,
|
|
|
|
|
chartType: props.chartType,
|
|
|
|
|
chartTitle: props.chartName,
|
|
|
|
|
});
|
|
|
|
|
const layoutConfig: Record<
|
|
|
|
|
string,
|
|
|
|
|
Record<string, unknown>
|
|
|
|
|
> = layoutBuilder.layoutConfig;
|
|
|
|
|
|
2023-07-28 13:29:16 +00:00
|
|
|
this.fontFamily = this.#evaluateFontFamily(props.fontFamily);
|
|
|
|
|
|
|
|
|
|
const chartConfig: Record<string, unknown> =
|
2023-08-18 13:50:39 +00:00
|
|
|
this.#defaultEChartConfig(layoutConfig);
|
|
|
|
|
chartConfig.title = this.#titleConfigForChart(
|
|
|
|
|
props,
|
|
|
|
|
allSeriesData,
|
|
|
|
|
layoutConfig,
|
|
|
|
|
);
|
|
|
|
|
chartConfig.xAxis = this.#xAxisConfig(props, layoutConfig);
|
|
|
|
|
chartConfig.yAxis = this.#yAxisConfig(props, layoutConfig);
|
|
|
|
|
|
|
|
|
|
chartConfig.dataZoom = this.#scrollConfig(props, layoutConfig);
|
2023-07-28 13:29:16 +00:00
|
|
|
chartConfig.series = this.#seriesConfigForChart(props, allSeriesData);
|
|
|
|
|
return chartConfig;
|
|
|
|
|
}
|
|
|
|
|
}
|