feat(plugin-chart-echarts): subject Update echarts to v5.0.1 (#928)

* feat(plugin-chart-echarts): subject Update echarts to v5.0.1

* fix lint

* fix lint

* wip

* wip

* wip

* Fix comments

* Add back missed properties

* Fix lint

* Fix
This commit is contained in:
Victor Malai 2021-02-04 11:34:51 +02:00 committed by Yongjie Zhao
parent 2a4cc71870
commit d3d343d6c4
11 changed files with 163 additions and 142 deletions

View File

@ -28,9 +28,8 @@
"dependencies": { "dependencies": {
"@superset-ui/chart-controls": "0.17.5", "@superset-ui/chart-controls": "0.17.5",
"@superset-ui/core": "0.17.5", "@superset-ui/core": "0.17.5",
"@types/echarts": "^4.9.3",
"@types/mathjs": "^6.0.7", "@types/mathjs": "^6.0.7",
"echarts": "^5.0.0", "echarts": "^5.0.1",
"mathjs": "^8.0.1" "mathjs": "^8.0.1"
}, },
"peerDependencies": { "peerDependencies": {

View File

@ -23,6 +23,8 @@ import {
getMetricLabel, getMetricLabel,
getNumberFormatter, getNumberFormatter,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { EChartsOption, BoxplotSeriesOption } from 'echarts';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { BoxPlotQueryFormData } from './types'; import { BoxPlotQueryFormData } from './types';
import { EchartsProps } from '../types'; import { EchartsProps } from '../types';
import { extractGroupbyLabel } from '../utils/series'; import { extractGroupbyLabel } from '../utils/series';
@ -43,7 +45,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
const metricLabels = formdataMetrics.map(getMetricLabel); const metricLabels = formdataMetrics.map(getMetricLabel);
const transformedData = data const transformedData = data
.map(datum => { .map((datum: any) => {
const groupbyLabel = extractGroupbyLabel({ datum, groupby }); const groupbyLabel = extractGroupbyLabel({ datum, groupby });
return metricLabels.map(metric => { return metricLabels.map(metric => {
const name = metricLabels.length === 1 ? groupbyLabel : `${groupbyLabel}, ${metric}`; const name = metricLabels.length === 1 ? groupbyLabel : `${groupbyLabel}, ${metric}`;
@ -102,41 +104,13 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
else if (xTicksLayout === 'staggered') axisLabel = { rotate: -45 }; else if (xTicksLayout === 'staggered') axisLabel = { rotate: -45 };
else axisLabel = { show: true }; else axisLabel = { show: true };
// @ts-ignore const series: BoxplotSeriesOption[] = [
const echartOptions: echarts.EChartOption<echarts.EChartOption.SeriesBoxplot> = {
grid: {
...defaultGrid,
top: 30,
bottom: 30,
left: 20,
right: 20,
},
xAxis: {
type: 'category',
data: transformedData.map(row => row.name),
axisLabel,
},
yAxis: {
...defaultYAxis,
type: 'value',
axisLabel: { formatter: numberFormatter },
},
tooltip: {
...defaultTooltip,
trigger: 'item',
axisPointer: {
type: 'shadow',
},
},
series: [
{ {
name: 'boxplot', name: 'boxplot',
type: 'boxplot', type: 'boxplot',
avoidLabelOverlap: true,
// @ts-ignore
data: transformedData, data: transformedData,
tooltip: { tooltip: {
formatter: param => { formatter: (param: CallbackDataParams) => {
// @ts-ignore // @ts-ignore
const { const {
value, value,
@ -164,7 +138,34 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
}, },
// @ts-ignore // @ts-ignore
...outlierData, ...outlierData,
], ];
const echartOptions: EChartsOption = {
grid: {
...defaultGrid,
top: 30,
bottom: 30,
left: 20,
right: 20,
},
xAxis: {
type: 'category',
data: transformedData.map(row => row.name),
axisLabel,
},
yAxis: {
...defaultYAxis,
type: 'value',
axisLabel: { formatter: numberFormatter },
},
tooltip: {
...defaultTooltip,
trigger: 'item',
axisPointer: {
type: 'shadow',
},
},
series,
}; };
return { return {

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
import { QueryFormData } from '@superset-ui/core'; import { QueryFormData } from '@superset-ui/core';
import { PostProcessingBoxplot } from '@superset-ui/core/src/query/types/PostProcessing'; import { PostProcessingBoxplot } from '@superset-ui/core/lib/query/types/PostProcessing';
export type BoxPlotQueryFormData = QueryFormData & { export type BoxPlotQueryFormData = QueryFormData & {
numberFormat?: string; numberFormat?: string;

View File

@ -25,6 +25,8 @@ import {
NumberFormats, NumberFormats,
NumberFormatter, NumberFormatter,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { EChartsOption, PieSeriesOption } from 'echarts';
import { import {
DEFAULT_FORM_DATA as DEFAULT_PIE_FORM_DATA, DEFAULT_FORM_DATA as DEFAULT_PIE_FORM_DATA,
EchartsPieFormData, EchartsPieFormData,
@ -41,7 +43,7 @@ export function formatPieLabel({
labelType, labelType,
numberFormatter, numberFormatter,
}: { }: {
params: echarts.EChartOption.Tooltip.Format; params: CallbackDataParams;
labelType: EchartsPieLabelType; labelType: EchartsPieLabelType;
numberFormatter: NumberFormatter; numberFormatter: NumberFormatter;
}): string { }): string {
@ -93,7 +95,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string); const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
const numberFormatter = getNumberFormatter(numberFormat); const numberFormatter = getNumberFormatter(numberFormat);
const transformedData = data.map(datum => { const transformedData: PieSeriesOption[] = data.map(datum => {
const name = extractGroupbyLabel({ datum, groupby }); const name = extractGroupbyLabel({ datum, groupby });
return { return {
value: datum[metricLabel], value: datum[metricLabel],
@ -104,7 +106,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
}; };
}); });
const formatter = (params: { name: string; value: number; percent: number }) => const formatter = (params: CallbackDataParams) =>
formatPieLabel({ params, numberFormatter, labelType }); formatPieLabel({ params, numberFormatter, labelType });
const defaultLabel = { const defaultLabel = {
@ -113,25 +115,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
color: '#000000', color: '#000000',
}; };
const echartOptions: echarts.EChartOption<echarts.EChartOption.SeriesPie> = { const series: PieSeriesOption[] = [
grid: {
...defaultGrid,
},
tooltip: {
...defaultTooltip,
trigger: 'item',
formatter: params =>
formatPieLabel({
params: params as echarts.EChartOption.Tooltip.Format,
numberFormatter,
labelType: EchartsPieLabelType.KeyValuePercent,
}),
},
legend: {
...getLegendProps(legendType, legendOrientation, showLegend),
data: keys,
},
series: [
{ {
type: 'pie', type: 'pie',
...getChartPadding(showLegend, legendOrientation, legendMargin), ...getChartPadding(showLegend, legendOrientation, legendMargin),
@ -158,10 +142,29 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
backgroundColor: 'white', backgroundColor: 'white',
}, },
}, },
// @ts-ignore
data: transformedData, data: transformedData,
}, },
], ];
const echartOptions: EChartsOption = {
grid: {
...defaultGrid,
},
tooltip: {
...defaultTooltip,
trigger: 'item',
formatter: (params: any) =>
formatPieLabel({
params,
numberFormatter,
labelType: EchartsPieLabelType.KeyValuePercent,
}),
},
legend: {
...getLegendProps(legendType, legendOrientation, showLegend),
data: keys,
},
series,
}; };
return { return {

View File

@ -32,6 +32,7 @@ import {
TimeseriesChartDataResponseResult, TimeseriesChartDataResponseResult,
TimeFormatter, TimeFormatter,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { EChartsOption, SeriesOption } from 'echarts';
import { DEFAULT_FORM_DATA, EchartsTimeseriesFormData } from './types'; import { DEFAULT_FORM_DATA, EchartsTimeseriesFormData } from './types';
import { EchartsProps, ForecastSeriesEnum, ProphetValue } from '../types'; import { EchartsProps, ForecastSeriesEnum, ProphetValue } from '../types';
import { parseYAxisBound } from '../utils/controls'; import { parseYAxisBound } from '../utils/controls';
@ -85,7 +86,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string); const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
const rebasedData = rebaseTimeseriesDatum(data); const rebasedData = rebaseTimeseriesDatum(data);
const rawSeries = extractTimeseriesSeries(rebasedData); const rawSeries = extractTimeseriesSeries(rebasedData);
const series: echarts.EChartOption.Series[] = []; const series: SeriesOption[] = [];
const formatter = getNumberFormatter(contributionMode ? ',.0%' : yAxisFormat); const formatter = getNumberFormatter(contributionMode ? ',.0%' : yAxisFormat);
rawSeries.forEach(entry => { rawSeries.forEach(entry => {
@ -136,7 +137,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
xAxisFormatter = String; xAxisFormatter = String;
} }
const echartOptions: echarts.EChartOption = { const echartOptions: EChartsOption = {
useUTC: true, useUTC: true,
grid: { grid: {
...defaultGrid, ...defaultGrid,
@ -168,7 +169,6 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
tooltip: { tooltip: {
...defaultTooltip, ...defaultTooltip,
trigger: richTooltip ? 'axis' : 'item', trigger: richTooltip ? 'axis' : 'item',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
formatter: (params: any) => { formatter: (params: any) => {
const value: number = !richTooltip ? params.value : params[0].value[0]; const value: number = !richTooltip ? params.value : params[0].value[0];
const prophetValue = !richTooltip ? [params] : params; const prophetValue = !richTooltip ? [params] : params;
@ -193,10 +193,12 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
}, },
legend: { legend: {
...getLegendProps(legendType, legendOrientation, showLegend), ...getLegendProps(legendType, legendOrientation, showLegend),
// @ts-ignore
data: rawSeries data: rawSeries
.filter( .filter(
entry => entry =>
extractForecastSeriesContext(entry.name || '').type === ForecastSeriesEnum.Observation, extractForecastSeriesContext((entry.name || '') as string).type ===
ForecastSeriesEnum.Observation,
) )
.map(entry => entry.name || '') .map(entry => entry.name || '')
.concat(extractAnnotationLabels(annotationLayers, annotationData)), .concat(extractAnnotationLabels(annotationLayers, annotationData)),
@ -227,7 +229,6 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
}; };
return { return {
// @ts-ignore
echartOptions, echartOptions,
width, width,
height, height,

View File

@ -18,15 +18,28 @@
*/ */
import { import {
AnnotationData, AnnotationData,
AnnotationLayer,
AnnotationOpacity, AnnotationOpacity,
CategoricalColorScale, CategoricalColorScale,
EventAnnotationLayer, EventAnnotationLayer,
FormulaAnnotationLayer,
IntervalAnnotationLayer, IntervalAnnotationLayer,
isTimeseriesAnnotationResult, isTimeseriesAnnotationResult,
TimeseriesAnnotationLayer, TimeseriesAnnotationLayer,
TimeseriesDataRecord, TimeseriesDataRecord,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { SeriesOption } from 'echarts';
import {
CallbackDataParams,
DefaultExtraStateOpts,
ItemStyleOption,
LineStyleOption,
OptionName,
ZRLineType,
} from 'echarts/types/src/util/types';
import {
MarkArea1DDataItemOption,
MarkArea2DDataItemOption,
} from 'echarts/types/src/component/marker/MarkAreaModel';
import { extractForecastSeriesContext } from '../utils/prophet'; import { extractForecastSeriesContext } from '../utils/prophet';
import { ForecastSeriesEnum } from '../types'; import { ForecastSeriesEnum } from '../types';
import { DEFAULT_FORM_DATA, EchartsTimeseriesFormData } from './types'; import { DEFAULT_FORM_DATA, EchartsTimeseriesFormData } from './types';
@ -38,10 +51,10 @@ import {
} from '../utils/annotation'; } from '../utils/annotation';
export function transformSeries( export function transformSeries(
series: echarts.EChartOption.Series, series: SeriesOption,
formData: EchartsTimeseriesFormData, formData: EchartsTimeseriesFormData,
colorScale: CategoricalColorScale, colorScale: CategoricalColorScale,
): echarts.EChartOption.Series | undefined { ): SeriesOption | undefined {
const { name } = series; const { name } = series;
const { const {
area, area,
@ -52,7 +65,7 @@ export function transformSeries(
seriesType, seriesType,
stack, stack,
richTooltip, richTooltip,
} = { }: EchartsTimeseriesFormData = {
...DEFAULT_FORM_DATA, ...DEFAULT_FORM_DATA,
...formData, ...formData,
}; };
@ -93,9 +106,10 @@ export function transformSeries(
itemStyle: { itemStyle: {
color: colorScale(forecastSeries.name), color: colorScale(forecastSeries.name),
}, },
type: plotType,
// @ts-ignore // @ts-ignore
type: plotType,
smooth: seriesType === 'smooth', smooth: seriesType === 'smooth',
// @ts-ignore
step: ['start', 'middle', 'end'].includes(seriesType as string) ? seriesType : undefined, step: ['start', 'middle', 'end'].includes(seriesType as string) ? seriesType : undefined,
stack: stackId, stack: stackId,
lineStyle, lineStyle,
@ -113,10 +127,10 @@ export function transformSeries(
} }
export function transformFormulaAnnotation( export function transformFormulaAnnotation(
layer: FormulaAnnotationLayer, layer: AnnotationLayer,
data: TimeseriesDataRecord[], data: TimeseriesDataRecord[],
colorScale: CategoricalColorScale, colorScale: CategoricalColorScale,
): echarts.EChartOption.Series { ): SeriesOption {
const { name, color, opacity, width, style } = layer; const { name, color, opacity, width, style } = layer;
return { return {
name, name,
@ -126,12 +140,11 @@ export function transformFormulaAnnotation(
}, },
lineStyle: { lineStyle: {
opacity: parseAnnotationOpacity(opacity), opacity: parseAnnotationOpacity(opacity),
type: style, type: style as ZRLineType,
width, width,
}, },
type: 'line', type: 'line',
smooth: true, smooth: true,
// @ts-ignore
data: evalFormula(layer, data), data: evalFormula(layer, data),
symbolSize: 0, symbolSize: 0,
z: 0, z: 0,
@ -143,14 +156,14 @@ export function transformIntervalAnnotation(
data: TimeseriesDataRecord[], data: TimeseriesDataRecord[],
annotationData: AnnotationData, annotationData: AnnotationData,
colorScale: CategoricalColorScale, colorScale: CategoricalColorScale,
): echarts.EChartOption.Series[] { ): SeriesOption[] {
const series: echarts.EChartOption.Series[] = []; const series: SeriesOption[] = [];
const annotations = extractRecordAnnotations(layer, annotationData); const annotations = extractRecordAnnotations(layer, annotationData);
annotations.forEach(annotation => { annotations.forEach(annotation => {
const { name, color, opacity } = layer; const { name, color, opacity } = layer;
const { descriptions, intervalEnd, time, title } = annotation; const { descriptions, intervalEnd, time, title } = annotation;
const label = formatAnnotationLabel(name, title, descriptions); const label = formatAnnotationLabel(name, title, descriptions);
const intervalData = [ const intervalData: (MarkArea1DDataItemOption | MarkArea2DDataItemOption)[] = [
[ [
{ {
name: label, name: label,
@ -173,10 +186,11 @@ export function transformIntervalAnnotation(
emphasis: { emphasis: {
opacity: 0.8, opacity: 0.8,
}, },
}, } as ItemStyleOption,
label: { label: {
show: false, show: false,
color: '#000000', color: '#000000',
// @ts-ignore
emphasis: { emphasis: {
fontWeight: 'bold', fontWeight: 'bold',
show: true, show: true,
@ -185,7 +199,6 @@ export function transformIntervalAnnotation(
backgroundColor: '#ffffff', backgroundColor: '#ffffff',
}, },
}, },
// @ts-ignore
data: intervalData, data: intervalData,
}, },
}); });
@ -198,8 +211,8 @@ export function transformEventAnnotation(
data: TimeseriesDataRecord[], data: TimeseriesDataRecord[],
annotationData: AnnotationData, annotationData: AnnotationData,
colorScale: CategoricalColorScale, colorScale: CategoricalColorScale,
): echarts.EChartOption.Series[] { ): SeriesOption[] {
const series: echarts.EChartOption.Series[] = []; const series: SeriesOption[] = [];
const annotations = extractRecordAnnotations(layer, annotationData); const annotations = extractRecordAnnotations(layer, annotationData);
annotations.forEach(annotation => { annotations.forEach(annotation => {
const { name, color, opacity, style, width } = layer; const { name, color, opacity, style, width } = layer;
@ -208,9 +221,21 @@ export function transformEventAnnotation(
const eventData = [ const eventData = [
{ {
name: label, name: label,
xAxis: time, xAxis: (time as unknown) as number,
}, },
]; ];
const lineStyle: LineStyleOption & DefaultExtraStateOpts['emphasis'] = {
width,
type: style as ZRLineType,
color: color || colorScale(name),
opacity: parseAnnotationOpacity(opacity),
emphasis: {
width: width ? width + 1 : width,
opacity: 1,
},
};
series.push({ series.push({
id: `Event - ${label}`, id: `Event - ${label}`,
type: 'line', type: 'line',
@ -218,32 +243,19 @@ export function transformEventAnnotation(
markLine: { markLine: {
silent: false, silent: false,
symbol: 'none', symbol: 'none',
lineStyle: { lineStyle,
width,
type: style,
color: color || colorScale(name),
opacity: parseAnnotationOpacity(opacity),
emphasis: {
width: width ? width + 1 : width,
opacity: 1,
},
},
label: { label: {
show: false, show: false,
color: '#000000', color: '#000000',
position: 'insideEndTop', position: 'insideEndTop',
// @ts-ignore
emphasis: { emphasis: {
// @ts-ignore formatter: (params: CallbackDataParams) => params.name,
formatter: params =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
params.name,
// @ts-ignore
fontWeight: 'bold', fontWeight: 'bold',
show: true, show: true,
backgroundColor: '#ffffff', backgroundColor: '#ffffff',
}, },
}, },
// @ts-ignore
data: eventData, data: eventData,
}, },
}); });
@ -256,8 +268,8 @@ export function transformTimeseriesAnnotation(
formData: EchartsTimeseriesFormData, formData: EchartsTimeseriesFormData,
data: TimeseriesDataRecord[], data: TimeseriesDataRecord[],
annotationData: AnnotationData, annotationData: AnnotationData,
): echarts.EChartOption.Series[] { ): SeriesOption[] {
const series: echarts.EChartOption.Series[] = []; const series: SeriesOption[] = [];
const { markerSize } = formData; const { markerSize } = formData;
const { hideLine, name, opacity, showMarkers, style, width } = layer; const { hideLine, name, opacity, showMarkers, style, width } = layer;
const result = annotationData[name]; const result = annotationData[name];
@ -268,11 +280,11 @@ export function transformTimeseriesAnnotation(
type: 'line', type: 'line',
id: key, id: key,
name: key, name: key,
data: values.map(row => [row.x, row.y] as [number | string, number]), data: values.map(row => [row.x, row.y] as [OptionName, number]),
symbolSize: showMarkers ? markerSize : 0, symbolSize: showMarkers ? markerSize : 0,
lineStyle: { lineStyle: {
opacity: parseAnnotationOpacity(opacity), opacity: parseAnnotationOpacity(opacity),
type: style, type: style as ZRLineType,
width: hideLine ? 0 : width, width: hideLine ? 0 : width,
}, },
}); });

View File

@ -18,7 +18,7 @@
*/ */
import React, { useRef, useEffect } from 'react'; import React, { useRef, useEffect } from 'react';
import { styled } from '@superset-ui/core'; import { styled } from '@superset-ui/core';
import { init } from 'echarts'; import { ECharts, init } from 'echarts';
import { EchartsProps, EchartsStylesProps } from '../types'; import { EchartsProps, EchartsStylesProps } from '../types';
const Styles = styled.div<EchartsStylesProps>` const Styles = styled.div<EchartsStylesProps>`
@ -28,7 +28,7 @@ const Styles = styled.div<EchartsStylesProps>`
export default function Echart({ width, height, echartOptions }: EchartsProps) { export default function Echart({ width, height, echartOptions }: EchartsProps) {
const divRef = useRef<HTMLDivElement>(null); const divRef = useRef<HTMLDivElement>(null);
const chartRef = useRef<echarts.ECharts>(); const chartRef = useRef<ECharts>();
useEffect(() => { useEffect(() => {
if (!divRef.current) return; if (!divRef.current) return;

View File

@ -16,6 +16,9 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import { EChartsOption } from 'echarts';
import { TooltipMarker } from 'echarts/types/src/util/format';
export type EchartsStylesProps = { export type EchartsStylesProps = {
height: number; height: number;
width: number; width: number;
@ -24,7 +27,7 @@ export type EchartsStylesProps = {
export interface EchartsProps { export interface EchartsProps {
height: number; height: number;
width: number; width: number;
echartOptions: echarts.EChartOption; echartOptions: EChartsOption;
} }
export enum ForecastSeriesEnum { export enum ForecastSeriesEnum {
@ -52,7 +55,7 @@ export enum LegendType {
} }
export type ProphetValue = { export type ProphetValue = {
marker: string; marker: TooltipMarker;
observation?: number; observation?: number;
forecastTrend?: number; forecastTrend?: number;
forecastLower?: number; forecastLower?: number;

View File

@ -23,7 +23,6 @@ import {
AnnotationLayer, AnnotationLayer,
AnnotationOpacity, AnnotationOpacity,
AnnotationType, AnnotationType,
FormulaAnnotationLayer,
isRecordAnnotationResult, isRecordAnnotationResult,
isTableAnnotationLayer, isTableAnnotationLayer,
isTimeseriesAnnotationResult, isTimeseriesAnnotationResult,
@ -32,11 +31,11 @@ import {
import { parse as mathjsParse } from 'mathjs'; import { parse as mathjsParse } from 'mathjs';
export function evalFormula( export function evalFormula(
formula: FormulaAnnotationLayer, formula: AnnotationLayer,
data: TimeseriesDataRecord[], data: TimeseriesDataRecord[],
): [Date, number][] { ): [Date, number][] {
const { value } = formula; const { value } = formula;
const node = mathjsParse(value); const node = mathjsParse(value as string);
const func = node.compile(); const func = node.compile();
return data.map(row => [ return data.map(row => [
new Date(Number(row.__timestamp)), new Date(Number(row.__timestamp)),

View File

@ -17,14 +17,17 @@
* under the License. * under the License.
*/ */
import { TimeseriesDataRecord, NumberFormatter } from '@superset-ui/core'; import { TimeseriesDataRecord, NumberFormatter } from '@superset-ui/core';
import { CallbackDataParams, OptionName } from 'echarts/types/src/util/types';
import { TooltipMarker } from 'echarts/types/src/util/format';
import { ForecastSeriesContext, ForecastSeriesEnum, ProphetValue } from '../types'; import { ForecastSeriesContext, ForecastSeriesEnum, ProphetValue } from '../types';
const seriesTypeRegex = new RegExp( const seriesTypeRegex = new RegExp(
`(.+)(${ForecastSeriesEnum.ForecastLower}|${ForecastSeriesEnum.ForecastTrend}|${ForecastSeriesEnum.ForecastUpper})$`, `(.+)(${ForecastSeriesEnum.ForecastLower}|${ForecastSeriesEnum.ForecastTrend}|${ForecastSeriesEnum.ForecastUpper})$`,
); );
export const extractForecastSeriesContext = (seriesName: string): ForecastSeriesContext => { export const extractForecastSeriesContext = (seriesName: OptionName): ForecastSeriesContext => {
const regexMatch = seriesTypeRegex.exec(seriesName); const name = seriesName as string;
if (!regexMatch) return { name: seriesName, type: ForecastSeriesEnum.Observation }; const regexMatch = seriesTypeRegex.exec(name);
if (!regexMatch) return { name, type: ForecastSeriesEnum.Observation };
return { return {
name: regexMatch[1], name: regexMatch[1],
type: regexMatch[2] as ForecastSeriesEnum, type: regexMatch[2] as ForecastSeriesEnum,
@ -32,7 +35,7 @@ export const extractForecastSeriesContext = (seriesName: string): ForecastSeries
}; };
export const extractProphetValuesFromTooltipParams = ( export const extractProphetValuesFromTooltipParams = (
params: (echarts.EChartOption.Tooltip.Format & { seriesId: string })[], params: (CallbackDataParams & { seriesId: string })[],
): Record<string, ProphetValue> => { ): Record<string, ProphetValue> => {
const values: Record<string, ProphetValue> = {}; const values: Record<string, ProphetValue> = {};
params.forEach(param => { params.forEach(param => {
@ -67,7 +70,7 @@ export const formatProphetTooltipSeries = ({
formatter, formatter,
}: ProphetValue & { }: ProphetValue & {
seriesName: string; seriesName: string;
marker: string; marker: TooltipMarker;
formatter: NumberFormatter; formatter: NumberFormatter;
}): string => { }): string => {
let row = `${marker}${seriesName}: `; let row = `${marker}${seriesName}: `;

View File

@ -24,13 +24,12 @@ import {
TimeFormatter, TimeFormatter,
TimeseriesDataRecord, TimeseriesDataRecord,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { LegendComponentOption, SeriesOption } from 'echarts';
import { NULL_STRING } from '../constants'; import { NULL_STRING } from '../constants';
import { LegendOrientation, LegendType } from '../types'; import { LegendOrientation, LegendType } from '../types';
import { defaultLegendPadding } from '../defaults'; import { defaultLegendPadding } from '../defaults';
export function extractTimeseriesSeries( export function extractTimeseriesSeries(data: TimeseriesDataRecord[]): SeriesOption[] {
data: TimeseriesDataRecord[],
): echarts.EChartOption.Series[] {
if (data.length === 0) return []; if (data.length === 0) return [];
const rows = data.map(datum => ({ const rows = data.map(datum => ({
...datum, ...datum,
@ -42,9 +41,10 @@ export function extractTimeseriesSeries(
.map(key => ({ .map(key => ({
id: key, id: key,
name: key, name: key,
// @ts-ignore data: rows.map((datum: { [p: string]: DataRecordValue; __timestamp: Date | null }) => [
// eslint-disable-next-line @typescript-eslint/no-unsafe-return datum.__timestamp,
data: rows.map(datum => [datum.__timestamp, datum[key]]), datum[key],
]),
})); }));
} }
@ -93,8 +93,8 @@ export function getLegendProps(
type: LegendType, type: LegendType,
orientation: LegendOrientation, orientation: LegendOrientation,
show: boolean, show: boolean,
): echarts.EChartOption.Legend { ): LegendComponentOption | LegendComponentOption[] {
const legend: echarts.EChartOption.Legend = { const legend: LegendComponentOption | LegendComponentOption[] = {
orient: [LegendOrientation.Top, LegendOrientation.Bottom].includes(orientation) orient: [LegendOrientation.Top, LegendOrientation.Bottom].includes(orientation)
? 'horizontal' ? 'horizontal'
: 'vertical', : 'vertical',