in superset-frontend/plugins/plugin-chart-echarts/src/Graph/transformProps.ts [156:372]
export default function transformProps(
chartProps: EchartsGraphChartProps,
): GraphChartTransformedProps {
const {
width,
height,
formData,
queriesData,
hooks,
inContextMenu,
filterState,
emitCrossFilters,
theme,
} = chartProps;
const data: DataRecord[] = queriesData[0].data || [];
const coltypeMapping = getColtypesMapping(queriesData[0]);
const {
source,
target,
sourceCategory,
targetCategory,
colorScheme,
metric = '',
layout,
roam,
draggable,
selectedMode,
showSymbolThreshold,
edgeLength,
gravity,
repulsion,
friction,
legendMargin,
legendOrientation,
legendType,
showLegend,
baseEdgeWidth,
baseNodeSize,
edgeSymbol,
sliceId,
}: EchartsGraphFormData = { ...DEFAULT_GRAPH_FORM_DATA, ...formData };
const refs: Refs = {};
const metricLabel = getMetricLabel(metric);
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
const firstColor = colorFn.range()[0];
const nodes: { [name: string]: number } = {};
const categories: Set<string> = new Set();
const echartNodes: EChartGraphNode[] = [];
const echartLinks: EdgeWithStyles[] = [];
/**
* Get the node id of an existing node,
* or create a new node if it doesn't exist.
*/
function getOrCreateNode(
name: string,
col: string,
category?: string,
color?: string,
) {
if (!(name in nodes)) {
nodes[name] = echartNodes.length;
echartNodes.push({
id: String(nodes[name]),
name,
col,
value: 0,
category,
select: DEFAULT_GRAPH_SERIES_OPTION.select,
tooltip: {
...getDefaultTooltip(refs),
...DEFAULT_GRAPH_SERIES_OPTION.tooltip,
},
itemStyle: { color },
});
}
const node = echartNodes[nodes[name]];
if (category) {
categories.add(category);
// category may be empty when one of `sourceCategory`
// or `targetCategory` is not set.
if (!node.category) {
node.category = category;
}
}
return node;
}
data.forEach(link => {
const value = link[metricLabel] as number;
if (!value) {
return;
}
const sourceName = link[source] as string;
const targetName = link[target] as string;
const sourceCategoryName = sourceCategory
? getCategoryName(sourceCategory, link[sourceCategory])
: undefined;
const targetCategoryName = targetCategory
? getCategoryName(targetCategory, link[targetCategory])
: undefined;
const sourceNodeColor = sourceCategoryName
? colorFn(sourceCategoryName)
: firstColor;
const targetNodeColor = targetCategoryName
? colorFn(targetCategoryName)
: firstColor;
const sourceNode = getOrCreateNode(
sourceName,
source,
sourceCategoryName,
sourceNodeColor,
);
const targetNode = getOrCreateNode(
targetName,
target,
targetCategoryName,
targetNodeColor,
);
sourceNode.value += value;
targetNode.value += value;
echartLinks.push({
source: sourceNode.id,
target: targetNode.id,
value,
lineStyle: {
color: sourceNodeColor,
},
emphasis: {},
select: {},
});
});
normalizeStyles(echartNodes, echartLinks, {
showSymbolThreshold,
baseEdgeWidth,
baseNodeSize,
});
const categoryList = [...categories];
const series: GraphSeriesOption[] = [
{
zoom: DEFAULT_GRAPH_SERIES_OPTION.zoom,
type: 'graph',
categories: categoryList.map(c => ({
name: c,
itemStyle: {
color: colorFn(c, sliceId),
},
})),
layout,
force: {
...DEFAULT_GRAPH_SERIES_OPTION.force,
edgeLength,
gravity,
repulsion,
friction,
},
circular: DEFAULT_GRAPH_SERIES_OPTION.circular,
data: echartNodes,
links: echartLinks,
roam,
draggable,
edgeSymbol: parseEdgeSymbol(edgeSymbol),
edgeSymbolSize: baseEdgeWidth * 2,
selectedMode,
...getChartPadding(showLegend, legendOrientation, legendMargin),
animation: DEFAULT_GRAPH_SERIES_OPTION.animation,
label: DEFAULT_GRAPH_SERIES_OPTION.label,
lineStyle: DEFAULT_GRAPH_SERIES_OPTION.lineStyle,
emphasis: DEFAULT_GRAPH_SERIES_OPTION.emphasis,
},
];
const echartOptions: EChartsCoreOption = {
animationDuration: DEFAULT_GRAPH_SERIES_OPTION.animationDuration,
animationEasing: DEFAULT_GRAPH_SERIES_OPTION.animationEasing,
tooltip: {
...getDefaultTooltip(refs),
show: !inContextMenu,
formatter: (params: any): string => {
const source = sanitizeHtml(
getKeyByValue(nodes, Number(params.data.source)),
);
const target = sanitizeHtml(
getKeyByValue(nodes, Number(params.data.target)),
);
const title = `${source} > ${target}`;
return tooltipHtml([[metricLabel, `${params.value}`]], title);
},
},
legend: {
...getLegendProps(legendType, legendOrientation, showLegend, theme),
data: categoryList,
},
series,
};
const { onContextMenu, setDataMask } = hooks;
return {
width,
height,
formData,
echartOptions,
onContextMenu,
setDataMask,
filterState,
refs,
emitCrossFilters,
coltypeMapping,
};
}