Skip to content

Commit

Permalink
feat: Adds drill to detail context menu for ECharts visualizations (#…
Browse files Browse the repository at this point in the history
…20891)

* feat: Adds drill to detail context menu for ECharts visualizations

* Rebases and adds time grain

* Fixes selected gauge values

* Fixes Treemap edge click

* Adds right click to big number trendline

* Address some comments
  • Loading branch information
michael-s-molina committed Aug 9, 2022
1 parent 0042ade commit 3df8335
Show file tree
Hide file tree
Showing 38 changed files with 734 additions and 249 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type Hooks = {
* also handles "change" and "remove".
*/
onAddFilter?: (newFilters: DataRecordFilters, merge?: boolean) => void;
/** handle right click */
onContextMenu?: HandlerFunction;
/** handle errors */
onError?: HandlerFunction;
/** use the vis as control to update state */
Expand Down Expand Up @@ -136,6 +138,8 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {

inputRef?: RefObject<any>;

inContextMenu?: boolean;

theme: SupersetTheme;

constructor(config: ChartPropsConfig & { formData?: FormData } = {}) {
Expand All @@ -154,6 +158,7 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
appSection,
isRefreshing,
inputRef,
inContextMenu = false,
theme,
} = config;
this.width = width;
Expand All @@ -172,6 +177,7 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
this.appSection = appSection;
this.isRefreshing = isRefreshing;
this.inputRef = inputRef;
this.inContextMenu = inContextMenu;
this.theme = theme;
}
}
Expand All @@ -193,6 +199,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector {
input => input.appSection,
input => input.isRefreshing,
input => input.inputRef,
input => input.inContextMenu,
input => input.theme,
(
annotationData,
Expand All @@ -209,6 +216,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector {
appSection,
isRefreshing,
inputRef,
inContextMenu,
theme,
) =>
new ChartProps({
Expand All @@ -226,6 +234,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector {
appSection,
isRefreshing,
inputRef,
inContextMenu,
theme,
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@ export type QueryObjectFilterClause = {
| {
op: BinaryOperator;
val: string | number | boolean;
formattedVal?: string;
}
| {
op: SetOperator;
val: (string | number | boolean)[];
formattedVal?: string[];
}
| {
op: UnaryOperator;
formattedVal?: string;
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export enum FeatureFlag {
USE_ANALAGOUS_COLORS = 'USE_ANALAGOUS_COLORS',
DASHBOARD_EDIT_CHART_IN_NEW_TAB = 'DASHBOARD_EDIT_CHART_IN_NEW_TAB',
EMBEDDABLE_CHARTS = 'EMBEDDABLE_CHARTS',
DRILL_TO_DETAIL = 'DRILL_TO_DETAIL',
}
export type ScheduleQueriesProps = {
JSONSCHEMA: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import { BigNumberTotalChartProps } from '../types';
import { getDateFormatter, parseMetricValue } from '../utils';

export default function transformProps(chartProps: BigNumberTotalChartProps) {
const { width, height, queriesData, formData, rawFormData } = chartProps;
const { width, height, queriesData, formData, rawFormData, hooks } =
chartProps;
const {
headerFontSize,
metric = 'value',
Expand Down Expand Up @@ -64,6 +65,8 @@ export default function transformProps(chartProps: BigNumberTotalChartProps) {
? formatTime
: getNumberFormatter(yAxisFormat ?? metricEntry?.d3format ?? undefined);

const { onContextMenu } = hooks;

return {
width,
height,
Expand All @@ -72,5 +75,6 @@ export default function transformProps(chartProps: BigNumberTotalChartProps) {
headerFontSize,
subheaderFontSize,
subheader: formattedSubheader,
onContextMenu,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import React, { MouseEvent } from 'react';
import {
t,
getNumberFormatter,
Expand All @@ -26,10 +26,12 @@ import {
computeMaxFontSize,
BRAND_COLOR,
styled,
QueryObjectFilterClause,
} from '@superset-ui/core';
import { EChartsCoreOption } from 'echarts';
import Echart from '../components/Echart';
import { TimeSeriesDatum } from './types';
import { BigNumberWithTrendlineFormData, TimeSeriesDatum } from './types';
import { EventHandlers } from '../types';

const defaultNumberFormatter = getNumberFormatter();

Expand Down Expand Up @@ -62,6 +64,13 @@ type BigNumberVisProps = {
trendLineData?: TimeSeriesDatum[];
mainColor: string;
echartOptions: EChartsCoreOption;
onContextMenu?: (
filters: QueryObjectFilterClause[],
offsetX: number,
offsetY: number,
) => void;
xValueFormatter?: TimeFormatter;
formData?: BigNumberWithTrendlineFormData;
};

class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
Expand Down Expand Up @@ -159,13 +168,25 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
});
container.remove();

const onContextMenu = (e: MouseEvent<HTMLDivElement>) => {
if (this.props.onContextMenu) {
e.preventDefault();
this.props.onContextMenu(
[],
e.nativeEvent.offsetX,
e.nativeEvent.offsetY,
);
}
};

return (
<div
className="header-line"
style={{
fontSize,
height: maxHeight,
}}
onContextMenu={onContextMenu}
>
{text}
</div>
Expand Down Expand Up @@ -213,19 +234,45 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
return null;
}

renderTrendline(maxHeight: number) {
renderTrendline(maxHeight: number, chartHeight: number) {
const { width, trendLineData, echartOptions } = this.props;

// if can't find any non-null values, no point rendering the trendline
if (!trendLineData?.some(d => d[1] !== null)) {
return null;
}

const eventHandlers: EventHandlers = {
contextmenu: eventParams => {
if (this.props.onContextMenu) {
eventParams.event.stop();
const { data } = eventParams;
if (data) {
const pointerEvent = eventParams.event.event;
const filters: QueryObjectFilterClause[] = [];
filters.push({
col: this.props.formData?.granularitySqla,
grain: this.props.formData?.timeGrainSqla,
op: '==',
val: data[0],
formattedVal: this.props.xValueFormatter?.(data[0]),
});
this.props.onContextMenu(
filters,
pointerEvent.offsetX,
chartHeight - 100,
);
}
}
},
};

return (
<Echart
width={Math.floor(width)}
height={maxHeight}
echartOptions={echartOptions}
eventHandlers={eventHandlers}
/>
);
}
Expand Down Expand Up @@ -260,7 +307,7 @@ class BigNumberVis extends React.PureComponent<BigNumberVisProps> {
),
)}
</div>
{this.renderTrendline(chartHeight)}
{this.renderTrendline(chartHeight, height)}
</div>
);
}
Expand All @@ -283,6 +330,7 @@ export default styled(BigNumberVis)`
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
&.no-trendline .subheader-line {
padding-bottom: 0.3em;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,16 @@ const formatPercentChange = getNumberFormatter(
export default function transformProps(
chartProps: BigNumberWithTrendlineChartProps,
) {
const { width, height, queriesData, formData, rawFormData, theme } =
chartProps;
const {
width,
height,
queriesData,
formData,
rawFormData,
theme,
hooks,
inContextMenu,
} = chartProps;
const {
colorPicker,
compareLag: compareLag_,
Expand Down Expand Up @@ -221,7 +229,7 @@ export default function transformProps(
},
tooltip: {
appendToBody: true,
show: true,
show: !inContextMenu,
trigger: 'axis',
confine: true,
formatter: renderTooltipFactory(formatTime, headerFormatter),
Expand All @@ -234,6 +242,9 @@ export default function transformProps(
},
}
: {};

const { onContextMenu } = hooks;

return {
width,
height,
Expand All @@ -242,6 +253,7 @@ export default function transformProps(
className,
headerFormatter,
formatTime,
formData,
headerFontSize,
subheaderFontSize,
mainColor,
Expand All @@ -252,5 +264,7 @@ export default function transformProps(
timestamp,
trendLineData,
echartOptions,
onContextMenu,
xValueFormatter: formatTime,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@
*/
import React, { useCallback } from 'react';
import Echart from '../components/Echart';
import { EventHandlers } from '../types';
import { allEventHandlers } from '../utils/eventHandlers';
import { BoxPlotChartTransformedProps } from './types';

export default function EchartsBoxPlot({
height,
width,
echartOptions,
setDataMask,
labelMap,
groupby,
selectedValues,
formData,
}: BoxPlotChartTransformedProps) {
export default function EchartsBoxPlot(props: BoxPlotChartTransformedProps) {
const {
height,
width,
echartOptions,
setDataMask,
labelMap,
groupby,
selectedValues,
formData,
} = props;
const handleChange = useCallback(
(values: string[]) => {
if (!formData.emitFilter) {
Expand Down Expand Up @@ -67,17 +68,7 @@ export default function EchartsBoxPlot({
[groupby, labelMap, setDataMask, selectedValues],
);

const eventHandlers: EventHandlers = {
click: props => {
const { name } = props;
const values = Object.values(selectedValues);
if (values.includes(name)) {
handleChange(values.filter(v => v !== name));
} else {
handleChange([name]);
}
},
};
const eventHandlers = allEventHandlers(props, handleChange);

return (
<Echart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,17 @@ import { OpacityEnum } from '../constants';
export default function transformProps(
chartProps: EchartsBoxPlotChartProps,
): BoxPlotChartTransformedProps {
const { width, height, formData, hooks, filterState, queriesData } =
chartProps;
const {
width,
height,
formData,
hooks,
filterState,
queriesData,
inContextMenu,
} = chartProps;
const { data = [] } = queriesData[0];
const { setDataMask = () => {} } = hooks;
const { setDataMask = () => {}, onContextMenu } = hooks;
const coltypeMapping = getColtypesMapping(queriesData[0]);
const {
colorScheme,
Expand Down Expand Up @@ -268,6 +275,7 @@ export default function transformProps(
},
tooltip: {
...defaultTooltip,
show: !inContextMenu,
trigger: 'item',
axisPointer: {
type: 'shadow',
Expand All @@ -286,5 +294,6 @@ export default function transformProps(
labelMap,
groupby,
selectedValues,
onContextMenu,
};
}

0 comments on commit 3df8335

Please sign in to comment.