/* * << * Davinci * == * Copyright (C) 2016 - 2017 EDP * == * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * >> */ import { IChartProps } from '../../components/Chart' import { decodeMetricName, getTextWidth } from '../../components/util' import { getLegendOption, getLabelOption } from './util' import { EChartOption } from 'echarts' import { getFormattedValue } from '../../components/Config/Format' import defaultTheme from 'assets/json/echartsThemes/default.project.json' const defaultThemeColors = defaultTheme.theme.color export default function (chartProps: IChartProps, drillOptions?: any) { const { width, height, data, cols, metrics, chartStyles, color, tip } = chartProps const { label, legend, spec, toolbox } = chartStyles const { legendPosition, fontSize } = legend const { circle, roseType } = spec const { selectedItems } = drillOptions // formatter: '{b}({d}%)' const labelOption = { label: getLabelOption('pie', label, metrics) } const roseTypeValue = roseType ? 'radius' : '' const radiusValue = (!circle && !roseType) || (!circle && roseType) ? `70%` : ['48%', '70%'] let seriesObj = {} const seriesArr = [] let legendData = [] let grouped: { [key: string]: object[] } = {} if (metrics.length <= 1) { const groupColumns = color.items .map((c) => c.name) .concat(cols.map((c) => c.name)) .reduce((distinctColumns, col) => { if (!distinctColumns.includes(col)) { distinctColumns.push(col) } return distinctColumns }, []) grouped = data.reduce<{ [key: string]: object[] }>((obj, val) => { const groupingKey = groupColumns .reduce((keyArr, col) => keyArr.concat(val[col]), []) .join(String.fromCharCode(0)) if (!obj[groupingKey]) { obj[groupingKey] = [] } obj[groupingKey].push(val) return obj }, {}) metrics.forEach((metric) => { const decodedMetricName = decodeMetricName(metric.name) const seriesData = [] Object.entries(grouped).forEach(([key, value]) => { const legendStr = key.replace(String.fromCharCode(0), ' ') legendData.push(legendStr) value.forEach((v) => { const obj = { name: legendStr, value: v[`${metric.agg}(${decodedMetricName})`] } seriesData.push(obj) }) }) let leftValue let topValue const pieLeft = 56 + Math.max(...legendData.map((s) => getTextWidth(s, '', `${fontSize}px`))) switch (legendPosition) { case 'top': leftValue = width / 2 topValue = (height + 32) / 2 break case 'bottom': leftValue = width / 2 topValue = (height - 32) / 2 break case 'left': leftValue = (width + pieLeft) / 2 topValue = height / 2 break case 'right': leftValue = (width - pieLeft) / 2 topValue = height / 2 break } seriesObj = { name: '', type: 'pie', avoidLabelOverlap: false, center: legend.showLegend ? [leftValue, topValue] : [width / 2, height / 2], data: seriesData.map((data, index) => { return { ...data, itemStyle: { normal: { ...color.items.length && { color: color.items[0].config.values[data.name] }, opacity: selectedItems && selectedItems.length ? selectedItems.includes(index) ? 1 : 0.25 : 1 } } } }), itemStyle: { emphasis: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } }, ...labelOption, roseType: roseTypeValue, radius: radiusValue } seriesArr.push(seriesObj) }) } else { legendData = [] seriesObj = { type: 'pie', avoidLabelOverlap: false, center: [width / 2, height / 2], data: metrics.map((metric, index) => { const decodedMetricName = decodeMetricName(metric.name) legendData.push(decodedMetricName) return { name: decodedMetricName, value: data.reduce((sum, record) => sum + record[`${metric.agg}(${decodedMetricName})`], 0), itemStyle: { normal: { color: color.value[metric.name] || defaultThemeColors[index % defaultThemeColors.length], opacity: selectedItems && selectedItems.length ? selectedItems.includes(index) ? 1 : 0.25 : 1 } } } }), itemStyle: { emphasis: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } }, ...labelOption, roseType: roseTypeValue, radius: radiusValue } seriesArr.push(seriesObj) } const tooltip: EChartOption.Tooltip = { trigger: 'item', formatter (params: EChartOption.Tooltip.Format) { const { color, name, value, percent, dataIndex } = params const tooltipLabels = [] if (color) { tooltipLabels.push( `` ) } tooltipLabels.push( `${name}
${getFormattedValue( value as number, metrics[metrics.length > 1 ? dataIndex : 0].format )}(${percent}%)` ) return tooltipLabels.join('') } } return { tooltip, legend: getLegendOption(legend, legendData), series: seriesArr } }