mirror of https://github.com/apache/superset.git
fix: Drill to detail blocked by tooltip (#22082)
Co-authored-by: Ville Brofeldt <ville.brofeldt@apple.com>
This commit is contained in:
parent
1809d2b957
commit
3bc0865d90
|
@ -23,10 +23,13 @@ import {
|
|||
extractTimegrain,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import { BigNumberTotalChartProps } from '../types';
|
||||
import { BigNumberTotalChartProps, BigNumberVizProps } from '../types';
|
||||
import { getDateFormatter, parseMetricValue } from '../utils';
|
||||
import { Refs } from '../../types';
|
||||
|
||||
export default function transformProps(chartProps: BigNumberTotalChartProps) {
|
||||
export default function transformProps(
|
||||
chartProps: BigNumberTotalChartProps,
|
||||
): BigNumberVizProps {
|
||||
const { width, height, queriesData, formData, rawFormData, hooks } =
|
||||
chartProps;
|
||||
const {
|
||||
|
@ -38,6 +41,7 @@ export default function transformProps(chartProps: BigNumberTotalChartProps) {
|
|||
timeFormat,
|
||||
yAxisFormat,
|
||||
} = formData;
|
||||
const refs: Refs = {};
|
||||
const { data = [], coltypes = [] } = queriesData[0];
|
||||
const granularity = extractTimegrain(rawFormData as QueryFormData);
|
||||
const metricName = getMetricLabel(metric);
|
||||
|
@ -76,5 +80,6 @@ export default function transformProps(chartProps: BigNumberTotalChartProps) {
|
|||
subheaderFontSize,
|
||||
subheader: formattedSubheader,
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,17 +20,14 @@ import React, { MouseEvent } from 'react';
|
|||
import {
|
||||
t,
|
||||
getNumberFormatter,
|
||||
NumberFormatter,
|
||||
smartDateVerboseFormatter,
|
||||
TimeFormatter,
|
||||
computeMaxFontSize,
|
||||
BRAND_COLOR,
|
||||
styled,
|
||||
BinaryQueryObjectFilterClause,
|
||||
} from '@superset-ui/core';
|
||||
import { EChartsCoreOption } from 'echarts';
|
||||
import Echart from '../components/Echart';
|
||||
import { BigNumberWithTrendlineFormData, TimeSeriesDatum } from './types';
|
||||
import { BigNumberVizProps } from './types';
|
||||
import { EventHandlers } from '../types';
|
||||
|
||||
const defaultNumberFormatter = getNumberFormatter();
|
||||
|
@ -44,36 +41,7 @@ const PROPORTION = {
|
|||
TRENDLINE: 0.3,
|
||||
};
|
||||
|
||||
type BigNumberVisProps = {
|
||||
className?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
bigNumber?: number | null;
|
||||
bigNumberFallback?: TimeSeriesDatum;
|
||||
headerFormatter: NumberFormatter | TimeFormatter;
|
||||
formatTime: TimeFormatter;
|
||||
headerFontSize: number;
|
||||
kickerFontSize: number;
|
||||
subheader: string;
|
||||
subheaderFontSize: number;
|
||||
showTimestamp?: boolean;
|
||||
showTrendLine?: boolean;
|
||||
startYAxisAtZero?: boolean;
|
||||
timeRangeFixed?: boolean;
|
||||
timestamp?: number;
|
||||
trendLineData?: TimeSeriesDatum[];
|
||||
mainColor: string;
|
||||
echartOptions: EChartsCoreOption;
|
||||
onContextMenu?: (
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
filters?: BinaryQueryObjectFilterClause[],
|
||||
) => void;
|
||||
xValueFormatter?: TimeFormatter;
|
||||
formData?: BigNumberWithTrendlineFormData;
|
||||
};
|
||||
|
||||
class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
||||
class BigNumberVis extends React.PureComponent<BigNumberVizProps> {
|
||||
static defaultProps = {
|
||||
className: '',
|
||||
headerFormatter: defaultNumberFormatter,
|
||||
|
@ -108,7 +76,7 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
|
||||
renderFallbackWarning() {
|
||||
const { bigNumberFallback, formatTime, showTimestamp } = this.props;
|
||||
if (!bigNumberFallback || showTimestamp) return null;
|
||||
if (!formatTime || !bigNumberFallback || showTimestamp) return null;
|
||||
return (
|
||||
<span
|
||||
className="alert alert-warning"
|
||||
|
@ -125,7 +93,13 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
|
||||
renderKicker(maxHeight: number) {
|
||||
const { timestamp, showTimestamp, formatTime, width } = this.props;
|
||||
if (!showTimestamp) return null;
|
||||
if (
|
||||
!formatTime ||
|
||||
!showTimestamp ||
|
||||
typeof timestamp === 'string' ||
|
||||
typeof timestamp === 'boolean'
|
||||
)
|
||||
return null;
|
||||
|
||||
const text = timestamp === null ? '' : formatTime(timestamp);
|
||||
|
||||
|
@ -155,6 +129,7 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
|
||||
renderHeader(maxHeight: number) {
|
||||
const { bigNumber, headerFormatter, width } = this.props;
|
||||
// @ts-ignore
|
||||
const text = bigNumber === null ? t('No data') : headerFormatter(bigNumber);
|
||||
|
||||
const container = this.createTemporaryContainer();
|
||||
|
@ -231,7 +206,7 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
}
|
||||
|
||||
renderTrendline(maxHeight: number) {
|
||||
const { width, trendLineData, echartOptions } = this.props;
|
||||
const { width, trendLineData, echartOptions, refs } = this.props;
|
||||
|
||||
// if can't find any non-null values, no point rendering the trendline
|
||||
if (!trendLineData?.some(d => d[1] !== null)) {
|
||||
|
@ -264,12 +239,15 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
};
|
||||
|
||||
return (
|
||||
<Echart
|
||||
width={Math.floor(width)}
|
||||
height={maxHeight}
|
||||
echartOptions={echartOptions}
|
||||
eventHandlers={eventHandlers}
|
||||
/>
|
||||
echartOptions && (
|
||||
<Echart
|
||||
refs={refs}
|
||||
width={Math.floor(width)}
|
||||
height={maxHeight}
|
||||
echartOptions={echartOptions}
|
||||
eventHandlers={eventHandlers}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -292,7 +270,9 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
<div className="text-container" style={{ height: allTextHeight }}>
|
||||
{this.renderFallbackWarning()}
|
||||
{this.renderKicker(
|
||||
Math.ceil(kickerFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
Math.ceil(
|
||||
(kickerFontSize || 0) * (1 - PROPORTION.TRENDLINE) * height,
|
||||
),
|
||||
)}
|
||||
{this.renderHeader(
|
||||
Math.ceil(headerFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
|
@ -311,7 +291,7 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
|
|||
return (
|
||||
<div className={className} style={{ height }}>
|
||||
{this.renderFallbackWarning()}
|
||||
{this.renderKicker(kickerFontSize * height)}
|
||||
{this.renderKicker((kickerFontSize || 0) * height)}
|
||||
{this.renderHeader(Math.ceil(headerFontSize * height))}
|
||||
{this.renderSubheader(Math.ceil(subheaderFontSize * height))}
|
||||
</div>
|
||||
|
|
|
@ -30,11 +30,14 @@ import {
|
|||
} from '@superset-ui/core';
|
||||
import { EChartsCoreOption, graphic } from 'echarts';
|
||||
import {
|
||||
BigNumberVizProps,
|
||||
BigNumberDatum,
|
||||
BigNumberWithTrendlineChartProps,
|
||||
TimeSeriesDatum,
|
||||
} from '../types';
|
||||
import { getDateFormatter, parseMetricValue } from '../utils';
|
||||
import { getDefaultPosition } from '../../utils/tooltip';
|
||||
import { Refs } from '../../types';
|
||||
|
||||
const defaultNumberFormatter = getNumberFormatter();
|
||||
export function renderTooltipFactory(
|
||||
|
@ -60,7 +63,7 @@ const formatPercentChange = getNumberFormatter(
|
|||
|
||||
export default function transformProps(
|
||||
chartProps: BigNumberWithTrendlineChartProps,
|
||||
) {
|
||||
): BigNumberVizProps {
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
|
@ -95,6 +98,7 @@ export default function transformProps(
|
|||
from_dttm: fromDatetime,
|
||||
to_dttm: toDatetime,
|
||||
} = queriesData[0];
|
||||
const refs: Refs = {};
|
||||
const metricName = getMetricLabel(metric);
|
||||
const compareLag = Number(compareLag_) || 0;
|
||||
let formattedSubheader = subheader;
|
||||
|
@ -103,7 +107,7 @@ export default function transformProps(
|
|||
const mainColor = `rgb(${r}, ${g}, ${b})`;
|
||||
|
||||
const xAxisLabel = getXAxisLabel(rawFormData) as string;
|
||||
let trendLineData;
|
||||
let trendLineData: TimeSeriesDatum[] | undefined;
|
||||
let percentChange = 0;
|
||||
let bigNumber = data.length === 0 ? null : data[0][metricName];
|
||||
let timestamp = data.length === 0 ? null : data[0][xAxisLabel];
|
||||
|
@ -144,6 +148,7 @@ export default function transformProps(
|
|||
}
|
||||
}
|
||||
sortedData.reverse();
|
||||
// @ts-ignore
|
||||
trendLineData = showTrendLine ? sortedData : undefined;
|
||||
}
|
||||
|
||||
|
@ -229,10 +234,10 @@ export default function transformProps(
|
|||
bottom: 0,
|
||||
},
|
||||
tooltip: {
|
||||
position: getDefaultPosition(refs),
|
||||
appendToBody: true,
|
||||
show: !inContextMenu,
|
||||
trigger: 'axis',
|
||||
confine: true,
|
||||
formatter: renderTooltipFactory(formatTime, headerFormatter),
|
||||
},
|
||||
aria: {
|
||||
|
@ -250,6 +255,7 @@ export default function transformProps(
|
|||
width,
|
||||
height,
|
||||
bigNumber,
|
||||
// @ts-ignore
|
||||
bigNumberFallback,
|
||||
className,
|
||||
headerFormatter,
|
||||
|
@ -267,5 +273,6 @@ export default function transformProps(
|
|||
echartOptions,
|
||||
onContextMenu,
|
||||
xValueFormatter: formatTime,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,12 +17,17 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { EChartsCoreOption } from 'echarts';
|
||||
import {
|
||||
BinaryQueryObjectFilterClause,
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
DataRecordValue,
|
||||
NumberFormatter,
|
||||
QueryFormData,
|
||||
QueryFormMetric,
|
||||
TimeFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { BaseChartProps, Refs } from '../types';
|
||||
|
||||
export interface BigNumberDatum {
|
||||
[key: string]: number | null;
|
||||
|
@ -43,15 +48,50 @@ export type BigNumberWithTrendlineFormData = BigNumberTotalFormData & {
|
|||
compareLag?: string | number;
|
||||
};
|
||||
|
||||
export type BigNumberTotalChartProps = ChartProps<QueryFormData> & {
|
||||
formData: BigNumberTotalFormData;
|
||||
queriesData: (ChartDataResponseResult & {
|
||||
data?: BigNumberDatum[];
|
||||
})[];
|
||||
};
|
||||
export interface BigNumberTotalChartDataResponseResult
|
||||
extends ChartDataResponseResult {
|
||||
data: BigNumberDatum[];
|
||||
}
|
||||
|
||||
export type BigNumberWithTrendlineChartProps = BigNumberTotalChartProps & {
|
||||
formData: BigNumberWithTrendlineFormData;
|
||||
};
|
||||
export type BigNumberTotalChartProps =
|
||||
BaseChartProps<BigNumberTotalFormData> & {
|
||||
formData: BigNumberTotalFormData;
|
||||
queriesData: BigNumberTotalChartDataResponseResult[];
|
||||
};
|
||||
|
||||
export type BigNumberWithTrendlineChartProps =
|
||||
BaseChartProps<BigNumberWithTrendlineFormData> & {
|
||||
formData: BigNumberWithTrendlineFormData;
|
||||
};
|
||||
|
||||
export type TimeSeriesDatum = [number, number | null];
|
||||
|
||||
export type BigNumberVizProps = {
|
||||
className?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
bigNumber?: DataRecordValue;
|
||||
bigNumberFallback?: TimeSeriesDatum;
|
||||
headerFormatter: NumberFormatter | TimeFormatter;
|
||||
formatTime?: TimeFormatter;
|
||||
headerFontSize: number;
|
||||
kickerFontSize?: number;
|
||||
subheader: string;
|
||||
subheaderFontSize: number;
|
||||
showTimestamp?: boolean;
|
||||
showTrendLine?: boolean;
|
||||
startYAxisAtZero?: boolean;
|
||||
timeRangeFixed?: boolean;
|
||||
timestamp?: DataRecordValue;
|
||||
trendLineData?: TimeSeriesDatum[];
|
||||
mainColor?: string;
|
||||
echartOptions?: EChartsCoreOption;
|
||||
onContextMenu?: (
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
filters?: BinaryQueryObjectFilterClause[],
|
||||
) => void;
|
||||
xValueFormatter?: TimeFormatter;
|
||||
formData?: BigNumberWithTrendlineFormData;
|
||||
refs: Refs;
|
||||
};
|
||||
|
|
|
@ -31,6 +31,7 @@ export default function EchartsBoxPlot(props: BoxPlotChartTransformedProps) {
|
|||
groupby,
|
||||
selectedValues,
|
||||
formData,
|
||||
refs,
|
||||
} = props;
|
||||
const handleChange = useCallback(
|
||||
(values: string[]) => {
|
||||
|
@ -72,6 +73,7 @@ export default function EchartsBoxPlot(props: BoxPlotChartTransformedProps) {
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -36,9 +36,11 @@ import {
|
|||
sanitizeHtml,
|
||||
} from '../utils/series';
|
||||
import { convertInteger } from '../utils/convertInteger';
|
||||
import { defaultGrid, defaultTooltip, defaultYAxis } from '../defaults';
|
||||
import { defaultGrid, defaultYAxis } from '../defaults';
|
||||
import { getPadding } from '../Timeseries/transformers';
|
||||
import { OpacityEnum } from '../constants';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
import { Refs } from '../types';
|
||||
|
||||
export default function transformProps(
|
||||
chartProps: EchartsBoxPlotChartProps,
|
||||
|
@ -71,6 +73,7 @@ export default function transformProps(
|
|||
yAxisTitlePosition,
|
||||
sliceId,
|
||||
} = formData as BoxPlotQueryFormData;
|
||||
const refs: Refs = {};
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const metricLabels = metrics.map(getMetricLabel);
|
||||
|
@ -270,7 +273,7 @@ export default function transformProps(
|
|||
nameLocation: yAxisTitlePosition === 'Left' ? 'middle' : 'end',
|
||||
},
|
||||
tooltip: {
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
show: !inContextMenu,
|
||||
trigger: 'item',
|
||||
axisPointer: {
|
||||
|
@ -291,5 +294,6 @@ export default function transformProps(
|
|||
groupby,
|
||||
selectedValues,
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { QueryFormData } from '@superset-ui/core';
|
||||
import {
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import { EchartsTitleFormData, EChartTransformedProps } from '../types';
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
TitleFormData,
|
||||
} from '../types';
|
||||
import { DEFAULT_TITLE_FORM_DATA } from '../constants';
|
||||
|
||||
export type BoxPlotQueryFormData = QueryFormData & {
|
||||
|
@ -29,7 +31,7 @@ export type BoxPlotQueryFormData = QueryFormData & {
|
|||
whiskerOptions?: BoxPlotFormDataWhiskerOptions;
|
||||
xTickLayout?: BoxPlotFormXTickLayout;
|
||||
emitFilter: boolean;
|
||||
} & EchartsTitleFormData;
|
||||
} & TitleFormData;
|
||||
|
||||
export type BoxPlotFormDataWhiskerOptions =
|
||||
| 'Tukey'
|
||||
|
@ -51,10 +53,11 @@ export const DEFAULT_FORM_DATA: BoxPlotQueryFormData = {
|
|||
};
|
||||
|
||||
export interface EchartsBoxPlotChartProps
|
||||
extends ChartProps<BoxPlotQueryFormData> {
|
||||
extends BaseChartProps<BoxPlotQueryFormData> {
|
||||
formData: BoxPlotQueryFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
export type BoxPlotChartTransformedProps =
|
||||
EChartTransformedProps<BoxPlotQueryFormData>;
|
||||
BaseTransformedProps<BoxPlotQueryFormData> &
|
||||
CrossFilterTransformedProps &
|
||||
ContextMenuTransformedProps;
|
||||
|
|
|
@ -31,6 +31,7 @@ export default function EchartsFunnel(props: FunnelChartTransformedProps) {
|
|||
groupby,
|
||||
selectedValues,
|
||||
formData,
|
||||
refs,
|
||||
} = props;
|
||||
const handleChange = useCallback(
|
||||
(values: string[]) => {
|
||||
|
@ -72,6 +73,7 @@ export default function EchartsFunnel(props: FunnelChartTransformedProps) {
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -40,8 +40,10 @@ import {
|
|||
getLegendProps,
|
||||
sanitizeHtml,
|
||||
} from '../utils/series';
|
||||
import { defaultGrid, defaultTooltip } from '../defaults';
|
||||
import { defaultGrid } from '../defaults';
|
||||
import { OpacityEnum, DEFAULT_LEGEND_FORM_DATA } from '../constants';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
import { Refs } from '../types';
|
||||
|
||||
const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
|
||||
|
||||
|
@ -115,6 +117,7 @@ export default function transformProps(
|
|||
...DEFAULT_FUNNEL_FORM_DATA,
|
||||
...formData,
|
||||
};
|
||||
const refs: Refs = {};
|
||||
const metricLabel = getMetricLabel(metric);
|
||||
const groupbyLabels = groupby.map(getColumnLabel);
|
||||
const keys = data.map(datum =>
|
||||
|
@ -212,7 +215,7 @@ export default function transformProps(
|
|||
...defaultGrid,
|
||||
},
|
||||
tooltip: {
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
show: !inContextMenu,
|
||||
trigger: 'item',
|
||||
formatter: (params: any) =>
|
||||
|
@ -240,5 +243,6 @@ export default function transformProps(
|
|||
groupby,
|
||||
selectedValues,
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,21 +16,20 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { QueryFormData } from '@superset-ui/core';
|
||||
import {
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EChartTransformedProps,
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
LegendFormData,
|
||||
LegendOrientation,
|
||||
LegendType,
|
||||
} from '../types';
|
||||
import { DEFAULT_LEGEND_FORM_DATA } from '../constants';
|
||||
|
||||
export type EchartsFunnelFormData = QueryFormData &
|
||||
EchartsLegendFormData & {
|
||||
LegendFormData & {
|
||||
colorScheme?: string;
|
||||
groupby: QueryFormData[];
|
||||
labelLine: boolean;
|
||||
|
@ -54,9 +53,8 @@ export enum EchartsFunnelLabelTypeType {
|
|||
}
|
||||
|
||||
export interface EchartsFunnelChartProps
|
||||
extends ChartProps<EchartsFunnelFormData> {
|
||||
extends BaseChartProps<EchartsFunnelFormData> {
|
||||
formData: EchartsFunnelFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
|
@ -76,4 +74,6 @@ export const DEFAULT_FORM_DATA: EchartsFunnelFormData = {
|
|||
};
|
||||
|
||||
export type FunnelChartTransformedProps =
|
||||
EChartTransformedProps<EchartsFunnelFormData>;
|
||||
BaseTransformedProps<EchartsFunnelFormData> &
|
||||
CrossFilterTransformedProps &
|
||||
ContextMenuTransformedProps;
|
||||
|
|
|
@ -31,6 +31,7 @@ export default function EchartsGauge(props: GaugeChartTransformedProps) {
|
|||
groupby,
|
||||
selectedValues,
|
||||
formData: { emitFilter },
|
||||
refs,
|
||||
} = props;
|
||||
const handleChange = useCallback(
|
||||
(values: string[]) => {
|
||||
|
@ -72,6 +73,7 @@ export default function EchartsGauge(props: GaugeChartTransformedProps) {
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -44,6 +44,8 @@ import {
|
|||
FONT_SIZE_MULTIPLIERS,
|
||||
} from './constants';
|
||||
import { OpacityEnum } from '../constants';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
import { Refs } from '../types';
|
||||
|
||||
const setIntervalBoundsAndColors = (
|
||||
intervals: string,
|
||||
|
@ -118,6 +120,7 @@ export default function transformProps(
|
|||
emitFilter,
|
||||
sliceId,
|
||||
}: EchartsGaugeFormData = { ...DEFAULT_GAUGE_FORM_DATA, ...formData };
|
||||
const refs: Refs = {};
|
||||
const data = (queriesData[0]?.data || []) as DataRecord[];
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
|
@ -258,6 +261,7 @@ export default function transformProps(
|
|||
color: gaugeSeriesOptions.detail?.color,
|
||||
};
|
||||
const tooltip = {
|
||||
position: getDefaultPosition(refs),
|
||||
formatter: (params: CallbackDataParams) => {
|
||||
const { name, value } = params;
|
||||
return `${name} : ${formatValue(value as number)}`;
|
||||
|
@ -300,6 +304,7 @@ export default function transformProps(
|
|||
axisTick,
|
||||
pointer,
|
||||
detail,
|
||||
// @ts-ignore
|
||||
tooltip,
|
||||
radius:
|
||||
Math.min(width, height) / 2 - axisLabelDistance - axisTickDistance,
|
||||
|
@ -327,5 +332,6 @@ export default function transformProps(
|
|||
groupby,
|
||||
selectedValues: filterState.selectedValues || [],
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { QueryFormColumn, QueryFormData } from '@superset-ui/core';
|
||||
import {
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
QueryFormColumn,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import { EChartTransformedProps } from '../types';
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
} from '../types';
|
||||
import { DEFAULT_LEGEND_FORM_DATA } from '../constants';
|
||||
|
||||
export type AxisTickLineStyle = {
|
||||
|
@ -80,10 +80,11 @@ export const DEFAULT_FORM_DATA: Partial<EchartsGaugeFormData> = {
|
|||
};
|
||||
|
||||
export interface EchartsGaugeChartProps
|
||||
extends ChartProps<EchartsGaugeFormData> {
|
||||
extends BaseChartProps<EchartsGaugeFormData> {
|
||||
formData: EchartsGaugeFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
export type GaugeChartTransformedProps =
|
||||
EChartTransformedProps<EchartsGaugeFormData>;
|
||||
BaseTransformedProps<EchartsGaugeFormData> &
|
||||
ContextMenuTransformedProps &
|
||||
CrossFilterTransformedProps;
|
||||
|
|
|
@ -34,6 +34,7 @@ export default function EchartsGraph({
|
|||
echartOptions,
|
||||
formData,
|
||||
onContextMenu,
|
||||
refs,
|
||||
}: GraphChartTransformedProps) {
|
||||
const eventHandlers: EventHandlers = {
|
||||
contextmenu: (e: Event) => {
|
||||
|
@ -68,6 +69,7 @@ export default function EchartsGraph({
|
|||
};
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
import {
|
||||
CategoricalColorNamespace,
|
||||
ChartProps,
|
||||
getMetricLabel,
|
||||
DataRecord,
|
||||
DataRecordValue,
|
||||
|
@ -32,9 +31,12 @@ import {
|
|||
DEFAULT_FORM_DATA as DEFAULT_GRAPH_FORM_DATA,
|
||||
EdgeSymbol,
|
||||
GraphChartTransformedProps,
|
||||
EchartsGraphChartProps,
|
||||
} from './types';
|
||||
import { DEFAULT_GRAPH_SERIES_OPTION } from './constants';
|
||||
import { getChartPadding, getLegendProps, sanitizeHtml } from '../utils/series';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
import { Refs } from '../types';
|
||||
|
||||
type EdgeWithStyles = GraphEdgeItemOption & {
|
||||
lineStyle: Exclude<GraphEdgeItemOption['lineStyle'], undefined>;
|
||||
|
@ -158,7 +160,7 @@ function getCategoryName(columnName: string, name?: DataRecordValue) {
|
|||
}
|
||||
|
||||
export default function transformProps(
|
||||
chartProps: ChartProps,
|
||||
chartProps: EchartsGraphChartProps,
|
||||
): GraphChartTransformedProps {
|
||||
const { width, height, formData, queriesData, hooks, inContextMenu } =
|
||||
chartProps;
|
||||
|
@ -294,11 +296,13 @@ export default function transformProps(
|
|||
},
|
||||
];
|
||||
|
||||
const refs: Refs = {};
|
||||
const echartOptions: EChartsCoreOption = {
|
||||
animationDuration: DEFAULT_GRAPH_SERIES_OPTION.animationDuration,
|
||||
animationEasing: DEFAULT_GRAPH_SERIES_OPTION.animationEasing,
|
||||
tooltip: {
|
||||
show: !inContextMenu,
|
||||
position: getDefaultPosition(refs),
|
||||
formatter: (params: any): string =>
|
||||
edgeFormatter(
|
||||
params.data.source,
|
||||
|
@ -322,5 +326,6 @@ export default function transformProps(
|
|||
formData,
|
||||
echartOptions,
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,16 +16,14 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
PlainObject,
|
||||
QueryFormData,
|
||||
BinaryQueryObjectFilterClause,
|
||||
} from '@superset-ui/core';
|
||||
import { QueryFormData } from '@superset-ui/core';
|
||||
import { GraphNodeItemOption } from 'echarts/types/src/chart/graph/GraphSeries';
|
||||
import { SeriesTooltipOption } from 'echarts/types/src/util/types';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EchartsProps,
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
LegendFormData,
|
||||
LegendOrientation,
|
||||
LegendType,
|
||||
} from '../types';
|
||||
|
@ -34,7 +32,7 @@ import { DEFAULT_LEGEND_FORM_DATA } from '../constants';
|
|||
export type EdgeSymbol = 'none' | 'circle' | 'arrow';
|
||||
|
||||
export type EchartsGraphFormData = QueryFormData &
|
||||
EchartsLegendFormData & {
|
||||
LegendFormData & {
|
||||
source: string;
|
||||
target: string;
|
||||
sourceCategory?: string;
|
||||
|
@ -85,11 +83,10 @@ export type tooltipFormatParams = {
|
|||
data: { [name: string]: string };
|
||||
};
|
||||
|
||||
export type GraphChartTransformedProps = EchartsProps & {
|
||||
formData: PlainObject;
|
||||
onContextMenu?: (
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
filters?: BinaryQueryObjectFilterClause[],
|
||||
) => void;
|
||||
};
|
||||
export interface EchartsGraphChartProps
|
||||
extends BaseChartProps<EchartsGraphFormData> {
|
||||
formData: EchartsGraphFormData;
|
||||
}
|
||||
|
||||
export type GraphChartTransformedProps =
|
||||
BaseTransformedProps<EchartsGraphFormData> & ContextMenuTransformedProps;
|
||||
|
|
|
@ -43,6 +43,7 @@ export default function EchartsMixedTimeseries({
|
|||
onContextMenu,
|
||||
xValueFormatter,
|
||||
xAxis,
|
||||
refs,
|
||||
}: EchartsMixedTimeseriesChartTransformedProps) {
|
||||
const isFirstQuery = useCallback(
|
||||
(seriesIndex: number) => seriesIndex < seriesBreakdown,
|
||||
|
@ -61,7 +62,7 @@ export default function EchartsMixedTimeseries({
|
|||
const currentGroupBy = isFirstQuery(seriesIndex) ? groupby : groupbyB;
|
||||
const currentLabelMap = isFirstQuery(seriesIndex) ? labelMap : labelMapB;
|
||||
const groupbyValues = values
|
||||
.map(value => currentLabelMap[value])
|
||||
.map(value => currentLabelMap?.[value])
|
||||
.filter(value => !!value);
|
||||
|
||||
setDataMask({
|
||||
|
@ -100,7 +101,7 @@ export default function EchartsMixedTimeseries({
|
|||
const eventHandlers: EventHandlers = {
|
||||
click: props => {
|
||||
const { seriesName, seriesIndex } = props;
|
||||
const values: string[] = Object.values(selectedValues);
|
||||
const values: string[] = Object.values(selectedValues || {});
|
||||
if (values.includes(seriesName)) {
|
||||
handleChange(
|
||||
values.filter(v => v !== seriesName),
|
||||
|
@ -162,6 +163,7 @@ export default function EchartsMixedTimeseries({
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -40,7 +40,11 @@ import {
|
|||
EchartsMixedTimeseriesChartTransformedProps,
|
||||
EchartsMixedTimeseriesProps,
|
||||
} from './types';
|
||||
import { EchartsTimeseriesSeriesType, ForecastSeriesEnum } from '../types';
|
||||
import {
|
||||
EchartsTimeseriesSeriesType,
|
||||
ForecastSeriesEnum,
|
||||
Refs,
|
||||
} from '../types';
|
||||
import { parseYAxisBound } from '../utils/controls';
|
||||
import {
|
||||
getOverMaxHiddenFormatter,
|
||||
|
@ -64,7 +68,7 @@ import {
|
|||
rebaseForecastDatum,
|
||||
} from '../utils/forecast';
|
||||
import { convertInteger } from '../utils/convertInteger';
|
||||
import { defaultGrid, defaultTooltip, defaultYAxis } from '../defaults';
|
||||
import { defaultGrid, defaultYAxis } from '../defaults';
|
||||
import {
|
||||
getPadding,
|
||||
getTooltipTimeFormatter,
|
||||
|
@ -76,6 +80,7 @@ import {
|
|||
transformTimeseriesAnnotation,
|
||||
} from '../Timeseries/transformers';
|
||||
import { TIMESERIES_CONSTANTS, TIMEGRAIN_TO_TIMESTAMP } from '../constants';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
|
||||
export default function transformProps(
|
||||
chartProps: EchartsMixedTimeseriesProps,
|
||||
|
@ -152,6 +157,7 @@ export default function transformProps(
|
|||
percentageThreshold,
|
||||
}: EchartsMixedTimeseriesFormData = { ...DEFAULT_FORM_DATA, ...formData };
|
||||
|
||||
const refs: Refs = {};
|
||||
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
|
||||
let xAxisLabel = getXAxisLabel(
|
||||
|
@ -419,7 +425,7 @@ export default function transformProps(
|
|||
},
|
||||
],
|
||||
tooltip: {
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
show: !inContextMenu,
|
||||
appendToBody: true,
|
||||
trigger: richTooltip ? 'axis' : 'item',
|
||||
|
@ -513,5 +519,6 @@ export default function transformProps(
|
|||
label: xAxisLabel,
|
||||
type: xAxisType,
|
||||
},
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,19 +20,20 @@ import {
|
|||
AnnotationLayer,
|
||||
TimeGranularity,
|
||||
QueryFormData,
|
||||
ChartProps,
|
||||
ChartDataResponseResult,
|
||||
QueryFormColumn,
|
||||
ContributionType,
|
||||
TimeFormatter,
|
||||
AxisType,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EchartsTitleFormData,
|
||||
StackType,
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
EchartsTimeseriesSeriesType,
|
||||
EChartTransformedProps,
|
||||
LegendFormData,
|
||||
StackType,
|
||||
TitleFormData,
|
||||
} from '../types';
|
||||
import {
|
||||
DEFAULT_LEGEND_FORM_DATA,
|
||||
|
@ -86,8 +87,8 @@ export type EchartsMixedTimeseriesFormData = QueryFormData & {
|
|||
groupby: QueryFormColumn[];
|
||||
groupbyB: QueryFormColumn[];
|
||||
emitFilter: boolean;
|
||||
} & EchartsLegendFormData &
|
||||
EchartsTitleFormData;
|
||||
} & LegendFormData &
|
||||
TitleFormData;
|
||||
|
||||
// @ts-ignore
|
||||
export const DEFAULT_FORM_DATA: EchartsMixedTimeseriesFormData = {
|
||||
|
@ -133,20 +134,22 @@ export const DEFAULT_FORM_DATA: EchartsMixedTimeseriesFormData = {
|
|||
...DEFAULT_TITLE_FORM_DATA,
|
||||
};
|
||||
|
||||
export interface EchartsMixedTimeseriesProps extends ChartProps {
|
||||
export interface EchartsMixedTimeseriesProps
|
||||
extends BaseChartProps<EchartsMixedTimeseriesFormData> {
|
||||
formData: EchartsMixedTimeseriesFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
export type EchartsMixedTimeseriesChartTransformedProps =
|
||||
EChartTransformedProps<EchartsMixedTimeseriesFormData> & {
|
||||
emitFilterB: boolean;
|
||||
groupbyB: QueryFormColumn[];
|
||||
labelMapB: Record<string, string[]>;
|
||||
seriesBreakdown: number;
|
||||
xValueFormatter: TimeFormatter | StringConstructor;
|
||||
xAxis: {
|
||||
label: string;
|
||||
type: AxisType;
|
||||
BaseTransformedProps<EchartsMixedTimeseriesFormData> &
|
||||
ContextMenuTransformedProps &
|
||||
CrossFilterTransformedProps & {
|
||||
emitFilterB: boolean;
|
||||
groupbyB: QueryFormColumn[];
|
||||
labelMapB: Record<string, string[]>;
|
||||
seriesBreakdown: number;
|
||||
xValueFormatter: TimeFormatter | StringConstructor;
|
||||
xAxis: {
|
||||
label: string;
|
||||
type: AxisType;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -31,6 +31,7 @@ export default function EchartsPie(props: PieChartTransformedProps) {
|
|||
groupby,
|
||||
selectedValues,
|
||||
formData,
|
||||
refs,
|
||||
} = props;
|
||||
const handleChange = useCallback(
|
||||
(values: string[]) => {
|
||||
|
@ -72,6 +73,7 @@ export default function EchartsPie(props: PieChartTransformedProps) {
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -43,8 +43,10 @@ import {
|
|||
getLegendProps,
|
||||
sanitizeHtml,
|
||||
} from '../utils/series';
|
||||
import { defaultGrid, defaultTooltip } from '../defaults';
|
||||
import { defaultGrid } from '../defaults';
|
||||
import { convertInteger } from '../utils/convertInteger';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
import { Refs } from '../types';
|
||||
|
||||
const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
|
||||
|
||||
|
@ -172,6 +174,7 @@ export default function transformProps(
|
|||
...DEFAULT_PIE_FORM_DATA,
|
||||
...formData,
|
||||
};
|
||||
const refs: Refs = {};
|
||||
const metricLabel = getMetricLabel(metric);
|
||||
const groupbyLabels = groupby.map(getColumnLabel);
|
||||
const minShowLabelAngle = (showLabelsThreshold || 0) * 3.6;
|
||||
|
@ -301,7 +304,7 @@ export default function transformProps(
|
|||
},
|
||||
tooltip: {
|
||||
show: !inContextMenu,
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
trigger: 'item',
|
||||
formatter: (params: any) =>
|
||||
formatPieLabel({
|
||||
|
@ -341,5 +344,6 @@ export default function transformProps(
|
|||
groupby,
|
||||
selectedValues,
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,22 +16,20 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { QueryFormColumn, QueryFormData } from '@superset-ui/core';
|
||||
import {
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
QueryFormColumn,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EChartTransformedProps,
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
LegendFormData,
|
||||
LegendOrientation,
|
||||
LegendType,
|
||||
} from '../types';
|
||||
import { DEFAULT_LEGEND_FORM_DATA } from '../constants';
|
||||
|
||||
export type EchartsPieFormData = QueryFormData &
|
||||
EchartsLegendFormData & {
|
||||
LegendFormData & {
|
||||
colorScheme?: string;
|
||||
currentOwnValue?: string[] | null;
|
||||
donut: boolean;
|
||||
|
@ -59,9 +57,9 @@ export enum EchartsPieLabelType {
|
|||
KeyValuePercent = 'key_value_percent',
|
||||
}
|
||||
|
||||
export interface EchartsPieChartProps extends ChartProps<EchartsPieFormData> {
|
||||
export interface EchartsPieChartProps
|
||||
extends BaseChartProps<EchartsPieFormData> {
|
||||
formData: EchartsPieFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
|
@ -84,4 +82,6 @@ export const DEFAULT_FORM_DATA: EchartsPieFormData = {
|
|||
};
|
||||
|
||||
export type PieChartTransformedProps =
|
||||
EChartTransformedProps<EchartsPieFormData>;
|
||||
BaseTransformedProps<EchartsPieFormData> &
|
||||
ContextMenuTransformedProps &
|
||||
CrossFilterTransformedProps;
|
||||
|
|
|
@ -31,6 +31,7 @@ export default function EchartsRadar(props: RadarChartTransformedProps) {
|
|||
groupby,
|
||||
selectedValues,
|
||||
formData,
|
||||
refs,
|
||||
} = props;
|
||||
const handleChange = useCallback(
|
||||
(values: string[]) => {
|
||||
|
@ -72,6 +73,7 @@ export default function EchartsRadar(props: RadarChartTransformedProps) {
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -42,7 +42,9 @@ import {
|
|||
getColtypesMapping,
|
||||
getLegendProps,
|
||||
} from '../utils/series';
|
||||
import { defaultGrid, defaultTooltip } from '../defaults';
|
||||
import { defaultGrid } from '../defaults';
|
||||
import { Refs } from '../types';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
|
||||
export function formatLabel({
|
||||
params,
|
||||
|
@ -79,6 +81,7 @@ export default function transformProps(
|
|||
theme,
|
||||
inContextMenu,
|
||||
} = chartProps;
|
||||
const refs: Refs = {};
|
||||
const { data = [] } = queriesData[0];
|
||||
const coltypeMapping = getColtypesMapping(queriesData[0]);
|
||||
|
||||
|
@ -229,7 +232,7 @@ export default function transformProps(
|
|||
...defaultGrid,
|
||||
},
|
||||
tooltip: {
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
show: !inContextMenu,
|
||||
trigger: 'item',
|
||||
},
|
||||
|
@ -255,5 +258,6 @@ export default function transformProps(
|
|||
groupby,
|
||||
selectedValues,
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
* under the License.
|
||||
*/
|
||||
import {
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
QueryFormColumn,
|
||||
QueryFormData,
|
||||
QueryFormMetric,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EChartTransformedProps,
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
LegendFormData,
|
||||
LabelPositionEnum,
|
||||
LegendOrientation,
|
||||
LegendType,
|
||||
|
@ -35,7 +36,7 @@ import { DEFAULT_LEGEND_FORM_DATA } from '../constants';
|
|||
type RadarColumnConfig = Record<string, { radarMetricMaxValue?: number }>;
|
||||
|
||||
export type EchartsRadarFormData = QueryFormData &
|
||||
EchartsLegendFormData & {
|
||||
LegendFormData & {
|
||||
colorScheme?: string;
|
||||
columnConfig?: RadarColumnConfig;
|
||||
currentOwnValue?: string[] | null;
|
||||
|
@ -57,9 +58,9 @@ export enum EchartsRadarLabelType {
|
|||
KeyValue = 'key_value',
|
||||
}
|
||||
|
||||
export interface EchartsRadarChartProps extends ChartProps {
|
||||
export interface EchartsRadarChartProps
|
||||
extends BaseChartProps<EchartsRadarFormData> {
|
||||
formData: EchartsRadarFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
|
@ -78,4 +79,6 @@ export const DEFAULT_FORM_DATA: EchartsRadarFormData = {
|
|||
};
|
||||
|
||||
export type RadarChartTransformedProps =
|
||||
EChartTransformedProps<EchartsRadarFormData>;
|
||||
BaseTransformedProps<EchartsRadarFormData> &
|
||||
ContextMenuTransformedProps &
|
||||
CrossFilterTransformedProps;
|
||||
|
|
|
@ -48,9 +48,12 @@ export default function EchartsTimeseries({
|
|||
onContextMenu,
|
||||
xValueFormatter,
|
||||
xAxis,
|
||||
refs,
|
||||
}: TimeseriesChartTransformedProps) {
|
||||
const { emitFilter, stack } = formData;
|
||||
const echartRef = useRef<EchartsHandler | null>(null);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
refs.echartRef = echartRef;
|
||||
const lastTimeRef = useRef(Date.now());
|
||||
const lastSelectedLegend = useRef('');
|
||||
const clickTimer = useRef<ReturnType<typeof setTimeout>>();
|
||||
|
@ -256,7 +259,7 @@ export default function EchartsTimeseries({
|
|||
<ExtraControls formData={formData} setControlValue={setControlValue} />
|
||||
</div>
|
||||
<Echart
|
||||
ref={echartRef}
|
||||
refs={refs}
|
||||
height={height - extraControlHeight}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -44,7 +44,7 @@ import {
|
|||
OrientationType,
|
||||
} from './types';
|
||||
import { DEFAULT_FORM_DATA } from './constants';
|
||||
import { ForecastSeriesEnum, ForecastValue } from '../types';
|
||||
import { ForecastSeriesEnum, ForecastValue, Refs } from '../types';
|
||||
import { parseYAxisBound } from '../utils/controls';
|
||||
import {
|
||||
currentSeries,
|
||||
|
@ -68,7 +68,7 @@ import {
|
|||
rebaseForecastDatum,
|
||||
} from '../utils/forecast';
|
||||
import { convertInteger } from '../utils/convertInteger';
|
||||
import { defaultGrid, defaultTooltip, defaultYAxis } from '../defaults';
|
||||
import { defaultGrid, defaultYAxis } from '../defaults';
|
||||
import {
|
||||
getPadding,
|
||||
getTooltipTimeFormatter,
|
||||
|
@ -84,6 +84,7 @@ import {
|
|||
TIMESERIES_CONSTANTS,
|
||||
TIMEGRAIN_TO_TIMESTAMP,
|
||||
} from '../constants';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
|
||||
export default function transformProps(
|
||||
chartProps: EchartsTimeseriesChartProps,
|
||||
|
@ -147,6 +148,7 @@ export default function transformProps(
|
|||
timeGrainSqla,
|
||||
orientation,
|
||||
}: EchartsTimeseriesFormData = { ...DEFAULT_FORM_DATA, ...formData };
|
||||
const refs: Refs = {};
|
||||
|
||||
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const rebasedData = rebaseForecastDatum(data, verboseMap);
|
||||
|
@ -380,7 +382,7 @@ export default function transformProps(
|
|||
yAxis,
|
||||
tooltip: {
|
||||
show: !inContextMenu,
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
appendToBody: true,
|
||||
trigger: richTooltip ? 'axis' : 'item',
|
||||
formatter: (params: any) => {
|
||||
|
@ -463,5 +465,6 @@ export default function transformProps(
|
|||
label: xAxisLabel,
|
||||
type: xAxisType,
|
||||
},
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,22 +16,24 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { OptionName } from 'echarts/types/src/util/types';
|
||||
import {
|
||||
AnnotationLayer,
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
AxisType,
|
||||
ContributionType,
|
||||
QueryFormColumn,
|
||||
QueryFormData,
|
||||
TimeGranularity,
|
||||
ContributionType,
|
||||
TimeFormatter,
|
||||
AxisType,
|
||||
TimeGranularity,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EChartTransformedProps,
|
||||
EchartsTitleFormData,
|
||||
BaseChartProps,
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
LegendFormData,
|
||||
StackType,
|
||||
TitleFormData,
|
||||
} from '../types';
|
||||
|
||||
export enum OrientationType {
|
||||
|
@ -85,20 +87,22 @@ export type EchartsTimeseriesFormData = QueryFormData & {
|
|||
showExtraControls: boolean;
|
||||
percentageThreshold: number;
|
||||
orientation?: OrientationType;
|
||||
} & EchartsLegendFormData &
|
||||
EchartsTitleFormData;
|
||||
} & LegendFormData &
|
||||
TitleFormData;
|
||||
|
||||
export interface EchartsTimeseriesChartProps
|
||||
extends ChartProps<EchartsTimeseriesFormData> {
|
||||
extends BaseChartProps<EchartsTimeseriesFormData> {
|
||||
formData: EchartsTimeseriesFormData;
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
export type TimeseriesChartTransformedProps =
|
||||
EChartTransformedProps<EchartsTimeseriesFormData> & {
|
||||
xValueFormatter: TimeFormatter | StringConstructor;
|
||||
xAxis: {
|
||||
label: string;
|
||||
type: AxisType;
|
||||
BaseTransformedProps<EchartsTimeseriesFormData> &
|
||||
ContextMenuTransformedProps &
|
||||
CrossFilterTransformedProps & {
|
||||
legendData?: OptionName[];
|
||||
xValueFormatter: TimeFormatter | StringConstructor;
|
||||
xAxis: {
|
||||
label: string;
|
||||
type: AxisType;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -21,9 +21,17 @@ import { EchartsProps } from '../types';
|
|||
import Echart from '../components/Echart';
|
||||
|
||||
export default function EchartsGraph({
|
||||
height,
|
||||
width,
|
||||
echartOptions,
|
||||
height,
|
||||
refs,
|
||||
width,
|
||||
}: EchartsProps) {
|
||||
return <Echart height={height} width={width} echartOptions={echartOptions} />;
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { TreeSeriesOption } from 'echarts';
|
||||
import { EchartsTreeFormData } from './types';
|
||||
|
||||
export const DEFAULT_TREE_SERIES_OPTION: TreeSeriesOption = {
|
||||
label: {
|
||||
|
@ -28,3 +29,18 @@ export const DEFAULT_TREE_SERIES_OPTION: TreeSeriesOption = {
|
|||
animationEasing: 'cubicOut',
|
||||
lineStyle: { color: 'source', width: 1.5 },
|
||||
};
|
||||
|
||||
export const DEFAULT_FORM_DATA: Partial<EchartsTreeFormData> = {
|
||||
id: '',
|
||||
parent: '',
|
||||
name: '',
|
||||
rootNodeId: '',
|
||||
layout: 'orthogonal',
|
||||
orient: 'LR',
|
||||
symbol: 'emptyCircle',
|
||||
symbolSize: 7,
|
||||
roam: true,
|
||||
nodeLabelPosition: 'left',
|
||||
childLabelPosition: 'bottom',
|
||||
emphasis: 'descendant',
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ import {
|
|||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
import { DEFAULT_FORM_DATA } from './constants';
|
||||
|
||||
const requiredEntity = {
|
||||
...sharedControls.entity,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ChartProps, getMetricLabel, DataRecordValue } from '@superset-ui/core';
|
||||
import { getMetricLabel, DataRecordValue } from '@superset-ui/core';
|
||||
import { EChartsCoreOption, TreeSeriesOption } from 'echarts';
|
||||
import {
|
||||
TreeSeriesCallbackDataParams,
|
||||
|
@ -24,12 +24,13 @@ import {
|
|||
} from 'echarts/types/src/chart/tree/TreeSeries';
|
||||
import { OptionName } from 'echarts/types/src/util/types';
|
||||
import {
|
||||
EchartsTreeChartProps,
|
||||
EchartsTreeFormData,
|
||||
DEFAULT_FORM_DATA as DEFAULT_GRAPH_FORM_DATA,
|
||||
TreeDataRecord,
|
||||
TreeTransformedProps,
|
||||
} from './types';
|
||||
import { DEFAULT_TREE_SERIES_OPTION } from './constants';
|
||||
import { EchartsProps } from '../types';
|
||||
import { DEFAULT_FORM_DATA, DEFAULT_TREE_SERIES_OPTION } from './constants';
|
||||
import { Refs } from '../types';
|
||||
|
||||
export function formatTooltip({
|
||||
params,
|
||||
|
@ -49,8 +50,11 @@ export function formatTooltip({
|
|||
].join('');
|
||||
}
|
||||
|
||||
export default function transformProps(chartProps: ChartProps): EchartsProps {
|
||||
export default function transformProps(
|
||||
chartProps: EchartsTreeChartProps,
|
||||
): TreeTransformedProps {
|
||||
const { width, height, formData, queriesData } = chartProps;
|
||||
const refs: Refs = {};
|
||||
const data: TreeDataRecord[] = queriesData[0].data || [];
|
||||
|
||||
const {
|
||||
|
@ -67,7 +71,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
|
|||
nodeLabelPosition,
|
||||
childLabelPosition,
|
||||
emphasis,
|
||||
}: EchartsTreeFormData = { ...DEFAULT_GRAPH_FORM_DATA, ...formData };
|
||||
}: EchartsTreeFormData = { ...DEFAULT_FORM_DATA, ...formData };
|
||||
const metricLabel = getMetricLabel(metric);
|
||||
|
||||
const nameColumn = name || id;
|
||||
|
@ -212,8 +216,10 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
|
|||
};
|
||||
|
||||
return {
|
||||
formData,
|
||||
width,
|
||||
height,
|
||||
echartOptions,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { OptionName } from 'echarts/types/src/util/types';
|
||||
import { ChartDataResponseResult, QueryFormData } from '@superset-ui/core';
|
||||
import { TreeSeriesNodeItemOption } from 'echarts/types/src/chart/tree/TreeSeries';
|
||||
import { BaseChartProps, BaseTransformedProps } from '../types';
|
||||
|
||||
export type EchartsTreeFormData = {
|
||||
export type EchartsTreeFormData = QueryFormData & {
|
||||
id: string;
|
||||
parent: string;
|
||||
name: string;
|
||||
|
@ -35,21 +38,18 @@ export type EchartsTreeFormData = {
|
|||
emphasis: 'none' | 'ancestor' | 'descendant';
|
||||
};
|
||||
|
||||
export const DEFAULT_FORM_DATA: EchartsTreeFormData = {
|
||||
id: '',
|
||||
parent: '',
|
||||
name: '',
|
||||
rootNodeId: '',
|
||||
layout: 'orthogonal',
|
||||
orient: 'LR',
|
||||
symbol: 'emptyCircle',
|
||||
symbolSize: 7,
|
||||
roam: true,
|
||||
nodeLabelPosition: 'left',
|
||||
childLabelPosition: 'bottom',
|
||||
emphasis: 'descendant',
|
||||
export interface TreeChartDataResponseResult extends ChartDataResponseResult {
|
||||
data: TreeDataRecord[];
|
||||
}
|
||||
|
||||
export interface EchartsTreeChartProps
|
||||
extends BaseChartProps<EchartsTreeFormData> {
|
||||
formData: EchartsTreeFormData;
|
||||
queriesData: TreeChartDataResponseResult[];
|
||||
}
|
||||
|
||||
export type TreeDataRecord = Record<string, OptionName> & {
|
||||
children?: TreeSeriesNodeItemOption[];
|
||||
};
|
||||
|
||||
export type TreeDataRecord = Record<string, string | number> & {
|
||||
children: TreeSeriesNodeItemOption[];
|
||||
};
|
||||
export type TreeTransformedProps = BaseTransformedProps<EchartsTreeFormData>;
|
||||
|
|
|
@ -28,15 +28,16 @@ import { extractTreePathInfo } from './constants';
|
|||
import { TreemapTransformedProps } from './types';
|
||||
|
||||
export default function EchartsTreemap({
|
||||
height,
|
||||
width,
|
||||
echartOptions,
|
||||
setDataMask,
|
||||
labelMap,
|
||||
groupby,
|
||||
selectedValues,
|
||||
formData,
|
||||
groupby,
|
||||
height,
|
||||
labelMap,
|
||||
onContextMenu,
|
||||
refs,
|
||||
setDataMask,
|
||||
selectedValues,
|
||||
width,
|
||||
}: TreemapTransformedProps) {
|
||||
const handleChange = useCallback(
|
||||
(values: string[]) => {
|
||||
|
@ -113,6 +114,7 @@ export default function EchartsTreemap({
|
|||
|
||||
return (
|
||||
<Echart
|
||||
refs={refs}
|
||||
height={height}
|
||||
width={width}
|
||||
echartOptions={echartOptions}
|
||||
|
|
|
@ -38,7 +38,6 @@ import {
|
|||
TreemapTransformedProps,
|
||||
} from './types';
|
||||
import { formatSeriesName, getColtypesMapping } from '../utils/series';
|
||||
import { defaultTooltip } from '../defaults';
|
||||
import {
|
||||
COLOR_SATURATION,
|
||||
BORDER_WIDTH,
|
||||
|
@ -48,6 +47,8 @@ import {
|
|||
BORDER_COLOR,
|
||||
} from './constants';
|
||||
import { OpacityEnum } from '../constants';
|
||||
import { getDefaultPosition } from '../utils/tooltip';
|
||||
import { Refs } from '../types';
|
||||
|
||||
export function formatLabel({
|
||||
params,
|
||||
|
@ -139,7 +140,7 @@ export default function transformProps(
|
|||
...DEFAULT_TREEMAP_FORM_DATA,
|
||||
...formData,
|
||||
};
|
||||
|
||||
const refs: Refs = {};
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const formatter = (params: TreemapSeriesCallbackDataParams) =>
|
||||
|
@ -309,7 +310,7 @@ export default function transformProps(
|
|||
|
||||
const echartOptions: EChartsCoreOption = {
|
||||
tooltip: {
|
||||
...defaultTooltip,
|
||||
position: getDefaultPosition(refs),
|
||||
show: !inContextMenu,
|
||||
trigger: 'item',
|
||||
formatter: (params: any) =>
|
||||
|
@ -332,5 +333,6 @@ export default function transformProps(
|
|||
groupby,
|
||||
selectedValues: filterState.selectedValues || [],
|
||||
onContextMenu,
|
||||
refs,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,7 +24,12 @@ import {
|
|||
QueryFormMetric,
|
||||
} from '@superset-ui/core';
|
||||
import { CallbackDataParams } from 'echarts/types/src/util/types';
|
||||
import { EChartTransformedProps, LabelPositionEnum } from '../types';
|
||||
import {
|
||||
BaseTransformedProps,
|
||||
ContextMenuTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
LabelPositionEnum,
|
||||
} from '../types';
|
||||
|
||||
export type EchartsTreemapFormData = QueryFormData & {
|
||||
colorScheme?: string;
|
||||
|
@ -73,4 +78,6 @@ export interface TreemapSeriesCallbackDataParams extends CallbackDataParams {
|
|||
}
|
||||
|
||||
export type TreemapTransformedProps =
|
||||
EChartTransformedProps<EchartsTreemapFormData>;
|
||||
BaseTransformedProps<EchartsTreemapFormData> &
|
||||
ContextMenuTransformedProps &
|
||||
CrossFilterTransformedProps;
|
||||
|
|
|
@ -42,10 +42,15 @@ function Echart(
|
|||
eventHandlers,
|
||||
zrEventHandlers,
|
||||
selectedValues = {},
|
||||
refs,
|
||||
}: EchartsProps,
|
||||
ref: React.Ref<EchartsHandler>,
|
||||
) {
|
||||
const divRef = useRef<HTMLDivElement>(null);
|
||||
if (refs) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
refs.divRef = divRef;
|
||||
}
|
||||
const chartRef = useRef<ECharts>();
|
||||
const currentSelection = useMemo(
|
||||
() => Object.keys(selectedValues) || [],
|
||||
|
@ -106,6 +111,7 @@ function Echart(
|
|||
// did mount
|
||||
useEffect(() => {
|
||||
handleSizeChange({ width, height });
|
||||
return () => chartRef.current?.dispose();
|
||||
}, []);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
import { JsonValue, t, TimeGranularity } from '@superset-ui/core';
|
||||
import { ReactNode } from 'react';
|
||||
import {
|
||||
EchartsLegendFormData,
|
||||
EchartsTitleFormData,
|
||||
LegendFormData,
|
||||
TitleFormData,
|
||||
LabelPositionEnum,
|
||||
LegendOrientation,
|
||||
LegendType,
|
||||
|
@ -91,14 +91,14 @@ export const TIMEGRAIN_TO_TIMESTAMP = {
|
|||
[TimeGranularity.YEAR]: 3600 * 1000 * 24 * 31 * 12,
|
||||
};
|
||||
|
||||
export const DEFAULT_LEGEND_FORM_DATA: EchartsLegendFormData = {
|
||||
export const DEFAULT_LEGEND_FORM_DATA: LegendFormData = {
|
||||
legendMargin: null,
|
||||
legendOrientation: LegendOrientation.Top,
|
||||
legendType: LegendType.Scroll,
|
||||
showLegend: true,
|
||||
};
|
||||
|
||||
export const DEFAULT_TITLE_FORM_DATA: EchartsTitleFormData = {
|
||||
export const DEFAULT_TITLE_FORM_DATA: TitleFormData = {
|
||||
xAxisTitle: '',
|
||||
xAxisTitleMargin: 0,
|
||||
yAxisTitle: '',
|
||||
|
@ -107,3 +107,10 @@ export const DEFAULT_TITLE_FORM_DATA: EchartsTitleFormData = {
|
|||
};
|
||||
|
||||
export { DEFAULT_FORM_DATA } from './Timeseries/constants';
|
||||
|
||||
// How far away from the mouse should the tooltip be
|
||||
export const TOOLTIP_POINTER_MARGIN = 10;
|
||||
|
||||
// If no satisfactory position can be found, how far away
|
||||
// from the edge of the window should the tooltip be kept
|
||||
export const TOOLTIP_OVERFLOW_MARGIN = 5;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { CallbackDataParams } from 'echarts/types/src/util/types';
|
||||
import { LegendOrientation } from './types';
|
||||
import { TOOLTIP_POINTER_MARGIN, TOOLTIP_OVERFLOW_MARGIN } from './constants';
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
|
@ -23,7 +25,59 @@ export const defaultGrid = {
|
|||
};
|
||||
|
||||
export const defaultTooltip = {
|
||||
confine: true,
|
||||
position: (
|
||||
canvasMousePos: [number, number],
|
||||
params: CallbackDataParams,
|
||||
tooltipDom: HTMLElement,
|
||||
rect: any,
|
||||
sizes: { contentSize: [number, number]; viewSize: [number, number] },
|
||||
) => {
|
||||
// algorithm copy-pasted from here:
|
||||
// https://github.com/apache/echarts/issues/5004#issuecomment-559668309
|
||||
|
||||
// The chart canvas position
|
||||
const canvasRect = tooltipDom.parentElement
|
||||
?.getElementsByTagName('canvas')[0]
|
||||
.getBoundingClientRect();
|
||||
|
||||
// The mouse coordinates relative to the whole window
|
||||
// The first parameter to the position function is the mouse position relative to the canvas
|
||||
const mouseX = canvasMousePos[0] + (canvasRect?.x || 0);
|
||||
const mouseY = canvasMousePos[1] + (canvasRect?.y || 0);
|
||||
|
||||
// The width and height of the tooltip dom element
|
||||
const tooltipWidth = sizes.contentSize[0];
|
||||
const tooltipHeight = sizes.contentSize[1];
|
||||
|
||||
// Start by placing the tooltip top and right relative to the mouse position
|
||||
let xPos = mouseX + TOOLTIP_POINTER_MARGIN;
|
||||
let yPos = mouseY - TOOLTIP_POINTER_MARGIN - tooltipHeight;
|
||||
|
||||
// The tooltip is overflowing past the right edge of the window
|
||||
if (xPos + tooltipWidth >= document.documentElement.clientWidth) {
|
||||
// Attempt to place the tooltip to the left of the mouse position
|
||||
xPos = mouseX - TOOLTIP_POINTER_MARGIN - tooltipWidth;
|
||||
|
||||
// The tooltip is overflowing past the left edge of the window
|
||||
if (xPos <= 0)
|
||||
// Place the tooltip a fixed distance from the left edge of the window
|
||||
xPos = TOOLTIP_OVERFLOW_MARGIN;
|
||||
}
|
||||
|
||||
// The tooltip is overflowing past the top edge of the window
|
||||
if (yPos <= 0) {
|
||||
// Attempt to place the tooltip to the bottom of the mouse position
|
||||
yPos = mouseY + TOOLTIP_POINTER_MARGIN;
|
||||
|
||||
// The tooltip is overflowing past the bottom edge of the window
|
||||
if (yPos + tooltipHeight >= document.documentElement.clientHeight)
|
||||
// Place the tooltip a fixed distance from the top edge of the window
|
||||
yPos = TOOLTIP_OVERFLOW_MARGIN;
|
||||
}
|
||||
|
||||
// Return the position (converted back to a relative position on the canvas)
|
||||
return [xPos - (canvasRect?.x || 0), yPos - (canvasRect?.y || 0)];
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultYAxis = {
|
||||
|
|
|
@ -16,15 +16,17 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React, { RefObject } from 'react';
|
||||
import {
|
||||
BinaryQueryObjectFilterClause,
|
||||
ChartDataResponseResult,
|
||||
ChartProps,
|
||||
HandlerFunction,
|
||||
QueryFormColumn,
|
||||
BinaryQueryObjectFilterClause,
|
||||
SetDataMaskHook,
|
||||
} from '@superset-ui/core';
|
||||
import { EChartsCoreOption, ECharts } from 'echarts';
|
||||
import { TooltipMarker } from 'echarts/types/src/util/format';
|
||||
import { OptionName } from 'echarts/types/src/util/types';
|
||||
import { AreaChartExtraControlsValue } from './constants';
|
||||
|
||||
export type EchartsStylesProps = {
|
||||
|
@ -32,6 +34,11 @@ export type EchartsStylesProps = {
|
|||
width: number;
|
||||
};
|
||||
|
||||
export type Refs = {
|
||||
echartRef?: React.Ref<EchartsHandler>;
|
||||
divRef?: RefObject<HTMLDivElement>;
|
||||
};
|
||||
|
||||
export interface EchartsProps {
|
||||
height: number;
|
||||
width: number;
|
||||
|
@ -40,6 +47,7 @@ export interface EchartsProps {
|
|||
zrEventHandlers?: EventHandlers;
|
||||
selectedValues?: Record<number, string>;
|
||||
forceClear?: boolean;
|
||||
refs: Refs;
|
||||
}
|
||||
|
||||
export interface EchartsHandler {
|
||||
|
@ -78,7 +86,7 @@ export type ForecastValue = {
|
|||
forecastUpper?: number;
|
||||
};
|
||||
|
||||
export type EchartsLegendFormData = {
|
||||
export type LegendFormData = {
|
||||
legendMargin: number | null | string;
|
||||
legendOrientation: LegendOrientation;
|
||||
legendType: LegendType;
|
||||
|
@ -103,26 +111,41 @@ export enum LabelPositionEnum {
|
|||
InsideBottomRight = 'insideBottomRight',
|
||||
}
|
||||
|
||||
export interface EChartTransformedProps<F> {
|
||||
export interface BaseChartProps<T> extends ChartProps<T> {
|
||||
queriesData: ChartDataResponseResult[];
|
||||
}
|
||||
|
||||
export interface BaseTransformedProps<F> {
|
||||
echartOptions: EChartsCoreOption;
|
||||
formData: F;
|
||||
height: number;
|
||||
width: number;
|
||||
echartOptions: EChartsCoreOption;
|
||||
emitFilter: boolean;
|
||||
setDataMask: SetDataMaskHook;
|
||||
setControlValue?: HandlerFunction;
|
||||
labelMap: Record<string, string[]>;
|
||||
groupby: QueryFormColumn[];
|
||||
selectedValues: Record<number, string>;
|
||||
legendData?: OptionName[];
|
||||
onContextMenu?: (
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
filters?: BinaryQueryObjectFilterClause[],
|
||||
) => void;
|
||||
refs: Refs;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export interface EchartsTitleFormData {
|
||||
export type CrossFilterTransformedProps = {
|
||||
emitFilter: boolean;
|
||||
groupby: QueryFormColumn[];
|
||||
labelMap: Record<string, string[]>;
|
||||
setControlValue?: HandlerFunction;
|
||||
setDataMask: SetDataMaskHook;
|
||||
selectedValues: Record<number, string>;
|
||||
};
|
||||
|
||||
export type ContextMenuTransformedProps = {
|
||||
onContextMenu?: (
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
filters?: BinaryQueryObjectFilterClause[],
|
||||
) => void;
|
||||
};
|
||||
|
||||
export interface TitleFormData {
|
||||
xAxisTitle: string;
|
||||
xAxisTitleMargin: number;
|
||||
yAxisTitle: string;
|
||||
|
|
|
@ -17,7 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { BinaryQueryObjectFilterClause } from '@superset-ui/core';
|
||||
import { EChartTransformedProps, EventHandlers } from '../types';
|
||||
import {
|
||||
BaseTransformedProps,
|
||||
CrossFilterTransformedProps,
|
||||
EventHandlers,
|
||||
} from '../types';
|
||||
|
||||
export type Event = {
|
||||
name: string;
|
||||
|
@ -40,8 +44,9 @@ export const clickEventHandler =
|
|||
|
||||
export const contextMenuEventHandler =
|
||||
(
|
||||
groupby: EChartTransformedProps<any>['groupby'],
|
||||
onContextMenu: EChartTransformedProps<any>['onContextMenu'],
|
||||
groupby: (BaseTransformedProps<any> &
|
||||
CrossFilterTransformedProps)['groupby'],
|
||||
onContextMenu: BaseTransformedProps<any>['onContextMenu'],
|
||||
labelMap: Record<string, string[]>,
|
||||
) =>
|
||||
(e: Event) => {
|
||||
|
@ -65,7 +70,7 @@ export const contextMenuEventHandler =
|
|||
};
|
||||
|
||||
export const allEventHandlers = (
|
||||
transformedProps: EChartTransformedProps<any>,
|
||||
transformedProps: BaseTransformedProps<any> & CrossFilterTransformedProps,
|
||||
handleChange: (values: string[]) => void,
|
||||
) => {
|
||||
const { groupby, selectedValues, onContextMenu, labelMap } = transformedProps;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { CallbackDataParams } from 'echarts/types/src/util/types';
|
||||
import { TOOLTIP_OVERFLOW_MARGIN, TOOLTIP_POINTER_MARGIN } from '../constants';
|
||||
import { Refs } from '../types';
|
||||
|
||||
export function getDefaultPosition(refs: Refs) {
|
||||
return (
|
||||
canvasMousePos: [number, number],
|
||||
params: CallbackDataParams,
|
||||
tooltipDom: HTMLDivElement | null,
|
||||
rect: any,
|
||||
sizes: { contentSize: [number, number]; viewSize: [number, number] },
|
||||
) => {
|
||||
// algorithm partially based on this snippet:
|
||||
// https://github.com/apache/echarts/issues/5004#issuecomment-559668309
|
||||
|
||||
// The chart canvas position
|
||||
const divRect = refs.divRef?.current?.getBoundingClientRect();
|
||||
|
||||
// The mouse coordinates relative to the whole window
|
||||
// The first parameter to the position function is the mouse position relative to the canvas
|
||||
const mouseX = canvasMousePos[0] + (divRect?.x || 0);
|
||||
const mouseY = canvasMousePos[1] + (divRect?.y || 0);
|
||||
|
||||
// The width and height of the tooltip dom element
|
||||
const tooltipWidth = sizes.contentSize[0];
|
||||
const tooltipHeight = sizes.contentSize[1];
|
||||
|
||||
// Start by placing the tooltip top and right relative to the mouse position
|
||||
let xPos = mouseX + TOOLTIP_POINTER_MARGIN;
|
||||
let yPos = mouseY - TOOLTIP_POINTER_MARGIN - tooltipHeight;
|
||||
|
||||
// The tooltip is overflowing past the right edge of the window
|
||||
if (xPos + tooltipWidth >= document.documentElement.clientWidth) {
|
||||
// Attempt to place the tooltip to the left of the mouse position
|
||||
xPos = mouseX - TOOLTIP_POINTER_MARGIN - tooltipWidth;
|
||||
|
||||
// The tooltip is overflowing past the left edge of the window
|
||||
if (xPos <= 0)
|
||||
// Place the tooltip a fixed distance from the left edge of the window
|
||||
xPos = TOOLTIP_OVERFLOW_MARGIN;
|
||||
}
|
||||
|
||||
// The tooltip is overflowing past the top edge of the window
|
||||
if (yPos <= 0) {
|
||||
// Attempt to place the tooltip to the bottom of the mouse position
|
||||
yPos = mouseY + TOOLTIP_POINTER_MARGIN;
|
||||
|
||||
// The tooltip is overflowing past the bottom edge of the window
|
||||
if (yPos + tooltipHeight >= document.documentElement.clientHeight)
|
||||
// Place the tooltip a fixed distance from the top edge of the window
|
||||
yPos = TOOLTIP_OVERFLOW_MARGIN;
|
||||
}
|
||||
|
||||
// Return the position (converted back to a relative position on the canvas)
|
||||
return [xPos - (divRect?.x || 0), yPos - (divRect?.y || 0)];
|
||||
};
|
||||
}
|
|
@ -25,6 +25,7 @@ import transformProps from '../../src/BigNumber/BigNumberWithTrendline/transform
|
|||
import {
|
||||
BigNumberDatum,
|
||||
BigNumberWithTrendlineChartProps,
|
||||
BigNumberWithTrendlineFormData,
|
||||
} from '../../src/BigNumber/types';
|
||||
|
||||
const formData = {
|
||||
|
@ -44,7 +45,8 @@ const formData = {
|
|||
datasource: 'test_datasource',
|
||||
};
|
||||
|
||||
const rawFormData = {
|
||||
const rawFormData: BigNumberWithTrendlineFormData = {
|
||||
colorPicker: { b: 0, g: 0, r: 0 },
|
||||
datasource: '1__table',
|
||||
metric: 'value',
|
||||
color_picker: {
|
||||
|
@ -129,7 +131,8 @@ describe('BigNumberWithTrendline', () => {
|
|||
expect(transformed.bigNumber).toStrictEqual(1.2345);
|
||||
expect(transformed.bigNumberFallback).not.toBeNull();
|
||||
|
||||
// should successfully formatTime by ganularity
|
||||
// should successfully formatTime by granularity
|
||||
// @ts-ignore
|
||||
expect(transformed.formatTime(new Date('2020-01-01'))).toStrictEqual(
|
||||
'2020-01-01 00:00:00',
|
||||
);
|
||||
|
@ -150,6 +153,7 @@ describe('BigNumberWithTrendline', () => {
|
|||
},
|
||||
};
|
||||
const transformed = transformProps(propsWithDatasource);
|
||||
// @ts-ignore
|
||||
expect(transformed.headerFormatter(transformed.bigNumber)).toStrictEqual(
|
||||
'1.23',
|
||||
);
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ChartProps, supersetTheme } from '@superset-ui/core';
|
||||
import { ChartProps, SqlaFormData, supersetTheme } from '@superset-ui/core';
|
||||
import transformProps from '../../src/Graph/transformProps';
|
||||
import { DEFAULT_GRAPH_SERIES_OPTION } from '../../src/Graph/constants';
|
||||
import { EchartsGraphChartProps } from '../../src/Graph/types';
|
||||
|
||||
describe('EchartsGraph transformProps', () => {
|
||||
it('should transform chart props for viz without category', () => {
|
||||
const formData = {
|
||||
const formData: SqlaFormData = {
|
||||
colorScheme: 'bnbColors',
|
||||
datasource: '3__table',
|
||||
granularity_sqla: 'ds',
|
||||
|
@ -30,6 +31,7 @@ describe('EchartsGraph transformProps', () => {
|
|||
source: 'source_column',
|
||||
target: 'target_column',
|
||||
category: null,
|
||||
viz_type: 'graph',
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
|
@ -57,7 +59,7 @@ describe('EchartsGraph transformProps', () => {
|
|||
};
|
||||
|
||||
const chartProps = new ChartProps(chartPropsConfig);
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsGraphChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -151,7 +153,7 @@ describe('EchartsGraph transformProps', () => {
|
|||
});
|
||||
|
||||
it('should transform chart props for viz with category and falsey normalization', () => {
|
||||
const formData = {
|
||||
const formData: SqlaFormData = {
|
||||
colorScheme: 'bnbColors',
|
||||
datasource: '3__table',
|
||||
granularity_sqla: 'ds',
|
||||
|
@ -160,6 +162,7 @@ describe('EchartsGraph transformProps', () => {
|
|||
target: 'target_column',
|
||||
sourceCategory: 'source_category_column',
|
||||
targetCategory: 'target_category_column',
|
||||
viz_type: 'graph',
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
|
@ -197,7 +200,7 @@ describe('EchartsGraph transformProps', () => {
|
|||
};
|
||||
|
||||
const chartProps = new ChartProps(chartPropsConfig);
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsGraphChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
import { ChartProps, supersetTheme } from '@superset-ui/core';
|
||||
import transformProps from '../../src/Tree/transformProps';
|
||||
import { EchartsTreeChartProps } from '../../src/Tree/types';
|
||||
|
||||
describe('EchartsTree transformProps', () => {
|
||||
const formData = {
|
||||
|
@ -70,7 +71,7 @@ describe('EchartsTree transformProps', () => {
|
|||
];
|
||||
|
||||
const chartProps = new ChartProps({ ...chartPropsConfig, queriesData });
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsTreeChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -137,7 +138,7 @@ describe('EchartsTree transformProps', () => {
|
|||
];
|
||||
|
||||
const chartProps = new ChartProps({ ...chartPropsConfig, queriesData });
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsTreeChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -223,7 +224,7 @@ describe('EchartsTree transformProps', () => {
|
|||
];
|
||||
|
||||
const chartProps = new ChartProps({ ...chartPropsConfig, queriesData });
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsTreeChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -299,7 +300,7 @@ describe('EchartsTree transformProps', () => {
|
|||
];
|
||||
|
||||
const chartProps = new ChartProps({ ...chartPropsConfig, queriesData });
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsTreeChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -385,7 +386,7 @@ describe('EchartsTree transformProps', () => {
|
|||
];
|
||||
|
||||
const chartProps = new ChartProps({ ...chartPropsConfig, queriesData });
|
||||
expect(transformProps(chartProps)).toEqual(
|
||||
expect(transformProps(chartProps as EchartsTreeChartProps)).toEqual(
|
||||
expect.objectContaining({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
|
Loading…
Reference in New Issue