@gooddata/react-components
Version:
GoodData.UI - A powerful JavaScript library for building analytical applications
156 lines (136 loc) • 5.48 kB
text/typescript
// (C) 2007-2020 GoodData Corporation
import pick = require("lodash/pick");
import set = require("lodash/set");
import get = require("lodash/get");
import Highcharts from "../highcharts/highchartsEntryPoint";
import {
isBubbleChart,
isComboChart,
isHeatmap,
isLineChart,
isOneOfTypes,
isScatterPlot,
isTreemap,
} from "../../utils/common";
import { VisualizationTypes } from "../../../../constants/visualizationTypes";
import { ILegendOptions, LegendOptionsItemType, DEFAULT_LEGEND_CONFIG } from "../../typings/legend";
import { supportedDualAxesChartTypes } from "../chartOptionsBuilder";
import { isStackedChart } from "./helpers";
function isHeatmapWithMultipleValues(chartOptions: any) {
const { type } = chartOptions;
const dataClasses: Highcharts.ColorAxisDataClassesOptions[] = get(
chartOptions,
"colorAxis.dataClasses",
[],
);
return isHeatmap(type) && dataClasses.length > 1;
}
export function shouldLegendBeEnabled(chartOptions: any) {
const seriesLength = get(chartOptions, "data.series.length");
const { type, hasStackByAttribute, hasViewByAttribute } = chartOptions;
const hasMoreThanOneSeries = seriesLength > 1;
const isLineChartStacked = isLineChart(type) && hasStackByAttribute;
const isStacked = isStackedChart(chartOptions);
const sliceTypes = [VisualizationTypes.PIE, VisualizationTypes.DONUT];
const isSliceChartWithViewByAttributeOrMultipleMeasures =
isOneOfTypes(type, sliceTypes) && (hasViewByAttribute || chartOptions.data.series[0].data.length > 1);
const isBubbleWithViewByAttribute = isBubbleChart(type) && hasViewByAttribute;
const isScatterPlotWithAttribute = isScatterPlot(type) && chartOptions.data.series[0].name;
const isTreemapWithViewByAttribute = isTreemap(type) && hasViewByAttribute;
const isTreemapWithManyCategories = isTreemap(type) && chartOptions.data.categories.length > 1;
return (
hasMoreThanOneSeries ||
isSliceChartWithViewByAttributeOrMultipleMeasures ||
isStacked ||
isLineChartStacked ||
isScatterPlotWithAttribute ||
isTreemapWithViewByAttribute ||
isBubbleWithViewByAttribute ||
isTreemapWithManyCategories ||
isHeatmapWithMultipleValues(chartOptions)
);
}
export function getLegendItems(chartOptions: any): LegendOptionsItemType[] {
const { type } = chartOptions;
const firstSeriesDataTypes = [
VisualizationTypes.PIE,
VisualizationTypes.DONUT,
VisualizationTypes.TREEMAP,
VisualizationTypes.FUNNEL,
VisualizationTypes.SCATTER,
];
if (isHeatmap(type)) {
const dataClasses: Highcharts.ColorAxisDataClassesOptions[] = get(
chartOptions,
"colorAxis.dataClasses",
[],
);
return dataClasses.map((dataClass, index) => {
const { from, to } = dataClass;
const color: string = dataClass.color as string; // wa are not using Gradient
const range = {
from,
to,
};
return {
range,
color,
legendIndex: index,
};
});
}
const legendDataSource = isOneOfTypes(type, firstSeriesDataTypes)
? chartOptions.data.series[0].data
: chartOptions.data.series;
let pickedProps = ["name", "color", "legendIndex"];
if (isOneOfTypes(type, supportedDualAxesChartTypes)) {
// 'yAxis' helps to distinguish primary and secondary axes
pickedProps = [...pickedProps, "yAxis"];
}
if (isComboChart(type)) {
pickedProps = [...pickedProps, "type"];
}
return legendDataSource
.filter((legendDataSourceItem: any) => legendDataSourceItem.showInLegend !== false)
.map((legendDataSourceItem: any) => pick(legendDataSourceItem, pickedProps));
}
export default function getLegend(legendConfig: any = {}, chartOptions: any): ILegendOptions {
const defaultLegendConfigByType = {};
const rightLegendCharts = [
VisualizationTypes.SCATTER,
VisualizationTypes.TREEMAP,
VisualizationTypes.BUBBLE,
VisualizationTypes.HEATMAP,
];
const defaultTopLegendCharts = [
VisualizationTypes.COLUMN,
VisualizationTypes.BAR,
VisualizationTypes.LINE,
VisualizationTypes.AREA,
VisualizationTypes.PIE,
VisualizationTypes.DONUT,
VisualizationTypes.BULLET,
VisualizationTypes.PUSHPIN,
];
if (legendConfig.position === "auto" || !legendConfig.position) {
if (isOneOfTypes(chartOptions.type, rightLegendCharts)) {
set(defaultLegendConfigByType, "position", "right");
}
if (isOneOfTypes(chartOptions.type, defaultTopLegendCharts) && !chartOptions.hasStackByAttribute) {
set(defaultLegendConfigByType, "position", "top");
}
}
const baseConfig = {
...DEFAULT_LEGEND_CONFIG,
...legendConfig,
...defaultLegendConfigByType, // TODO: swipe these two lines once default legend logic is moved to the sdk
};
const isLegendEnabled = shouldLegendBeEnabled(chartOptions);
return {
...baseConfig,
enabled: baseConfig.enabled && isLegendEnabled,
toggleEnabled: isLegendEnabled,
format: get(chartOptions, "title.format", ""),
items: getLegendItems(chartOptions),
};
}