/* * << * 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 'containers/Widget/components/Chart' import { decodeMetricName, metricAxisLabelFormatter } from 'containers/Widget/components/util' import { getLegendOption, getGridPositions, getDimetionAxisOption, getCartesianChartReferenceOptions } from './util' import { getFormattedValue } from 'containers/Widget/components/Config/Format' import { getFieldAlias } from 'containers/Widget/components/Config/Field' import ChartTypes from 'containers/Widget/config/chart/ChartTypes' import { getMetricsExtendMinAndMax } from './helper' export default function (chartProps: IChartProps, drillOptions) { const { data, cols, metrics, chartStyles, // color, // tip, references } = chartProps const { legend, spec, doubleYAxis, xAxis, splitLine } = chartStyles const { stack, smooth, step, symbol, label } = spec const { yAxisLeft, yAxisRight, yAxisSplitNumber } = doubleYAxis const { showLabel } = xAxis const { showVerticalLine, verticalLineColor, verticalLineSize, verticalLineStyle } = splitLine const labelOption = { label: { normal: { show: label, position: 'top' } } } const { selectedItems } = drillOptions const { secondaryMetrics } = chartProps const xAxisData = showLabel ? data.map((d) => d[cols[0].name]) : [] const seriesData = secondaryMetrics ? getAixsMetrics( 'metrics', metrics, data, stack, labelOption, references, selectedItems, { key: 'yAxisLeft', type: yAxisLeft } ).concat( getAixsMetrics( 'secondaryMetrics', secondaryMetrics, data, stack, labelOption, references, selectedItems, { key: 'yAxisRight', type: yAxisRight } ) ) : getAixsMetrics( 'metrics', metrics, data, stack, labelOption, references, selectedItems, { key: 'yAxisLeft', type: yAxisLeft } ) const seriesObj = { series: seriesData.map((series) => { if (series.type === 'line') { return { ...series, symbol: symbol ? 'emptyCircle' : 'none', smooth, step } } else { return series } }) } let legendOption let gridOptions if (seriesData.length > 1) { const seriesNames = seriesData.map((s) => s.name) legendOption = { legend: getLegendOption(legend, seriesNames) } gridOptions = { grid: getGridPositions( legend, seriesNames, 'doubleYAxis', false, null, xAxis, xAxisData ) } } const xAxisSplitLineConfig = { showLine: showVerticalLine, lineColor: verticalLineColor, lineSize: verticalLineSize, lineStyle: verticalLineStyle } const allMetrics = secondaryMetrics ? [].concat(metrics).concat(secondaryMetrics) : metrics const { leftY, rightY } = getMetricsExtendMinAndMax( metrics, secondaryMetrics, data, stack, yAxisSplitNumber ) const [leftExtentMin, leftExtentMax, leftInterval] = leftY const [rightExtentMin, rightExtentMax, rightInterval] = rightY const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'cross' }, formatter(params) { const tooltipLabels = [ getFormattedValue(params[0].name, cols[0].format), '
' ] params.reduce((acc, param) => { const { color, value, seriesIndex } = param if (color) { acc.push( `` ) } acc.push( getFieldAlias(allMetrics[seriesIndex].field, {}) || decodeMetricName(allMetrics[seriesIndex].name) ) acc.push( ': ', getFormattedValue(value, allMetrics[seriesIndex].format), '
' ) return acc }, tooltipLabels) return tooltipLabels.join('') } }, xAxis: getDimetionAxisOption(xAxis, xAxisSplitLineConfig, xAxisData), yAxis: [ { type: 'value', key: 'yAxisIndex0', min: rightExtentMin, max: rightExtentMax, interval: +rightInterval, position: 'right', showTitleAndUnit: true, name: getYAxisName(secondaryMetrics), nameLocation: 'middle', nameGap: 50, nameRotate: 90, nameTextStyle: { color: '#666', fontFamily: 'PingFang SC', fontSize: 12 }, ...getDoubleYAxis(doubleYAxis) }, { type: 'value', key: 'yAxisIndex1', min: leftExtentMin, max: leftExtentMax, interval: +leftInterval, position: 'left', showTitleAndUnit: true, name: getYAxisName(metrics), nameLocation: 'middle', nameGap: 50, nameRotate: 90, nameTextStyle: { color: '#666', fontFamily: 'PingFang SC', fontSize: 12 }, ...getDoubleYAxis(doubleYAxis) } ], ...seriesObj, ...gridOptions, ...legendOption } return option } export function getAixsMetrics( type, axisMetrics, data, stack, labelOption, references, selectedItems, axisPosition?: { key: string; type: string } ) { const seriesNames = [] const seriesAxis = [] const referenceOptions = getCartesianChartReferenceOptions( references, ChartTypes.DoubleYAxis, axisMetrics, data ) axisMetrics.forEach((m, amIndex) => { const decodedMetricName = decodeMetricName(m.name) seriesNames.push(decodedMetricName) const stackOption = stack && axisPosition.type === 'bar' && axisMetrics.length > 1 ? { stack: axisPosition.key } : null const itemData = data.map((g, index) => { const itemStyle = selectedItems && selectedItems.length && selectedItems.some((item) => item === index) ? { itemStyle: { normal: { opacity: 1, borderWidth: 6 } } } : null return { value: g[`${m.agg}(${decodedMetricName})`], ...itemStyle } }) seriesAxis.push({ name: decodedMetricName, type: axisPosition && axisPosition.type ? axisPosition.type : type === 'metrics' ? 'line' : 'bar', ...stackOption, yAxisIndex: type === 'metrics' ? 1 : 0, data: itemData, ...labelOption, ...(amIndex === axisMetrics.length - 1 && referenceOptions), itemStyle: { normal: { opacity: selectedItems && selectedItems.length > 0 ? 0.25 : 1 } } }) }) return seriesAxis } export function getYAxisName(metrics) { return metrics .map((m) => (m.field.alias ? m.field.alias : decodeMetricName(m.name))) .join(` / `) } export function getDoubleYAxis(doubleYAxis) { const { inverse, showLine, lineStyle, lineSize, lineColor, showLabel, labelFontFamily, labelFontSize, labelColor } = doubleYAxis return { inverse, axisLine: { show: showLine, lineStyle: { color: lineColor, width: Number(lineSize), type: lineStyle } }, axisLabel: { show: showLabel, color: labelColor, fontFamily: labelFontFamily, fontSize: Number(labelFontSize), formatter: metricAxisLabelFormatter } } }