feat: Adds drill to detail context menu for ECharts visualizations (#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
This commit is contained in:
Michael S. Molina
2022-08-09 17:02:31 -03:00
committed by GitHub
parent 0042ade66f
commit 3df8335f87
38 changed files with 734 additions and 249 deletions

View File

@@ -19,9 +19,17 @@
import { snakeCase, isEqual } from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import { SuperChart, logging, Behavior, t } from '@superset-ui/core';
import {
SuperChart,
logging,
Behavior,
t,
isFeatureEnabled,
FeatureFlag,
} from '@superset-ui/core';
import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils';
import { EmptyStateBig, EmptyStateSmall } from 'src/components/EmptyState';
import ChartContextMenu from './ChartContextMenu';
const propTypes = {
annotationData: PropTypes.object,
@@ -73,15 +81,28 @@ const defaultProps = {
class ChartRenderer extends React.Component {
constructor(props) {
super(props);
this.state = {
inContextMenu: false,
};
this.hasQueryResponseChange = false;
this.contextMenuRef = React.createRef();
this.handleAddFilter = this.handleAddFilter.bind(this);
this.handleRenderSuccess = this.handleRenderSuccess.bind(this);
this.handleRenderFailure = this.handleRenderFailure.bind(this);
this.handleSetControlValue = this.handleSetControlValue.bind(this);
this.handleOnContextMenu = this.handleOnContextMenu.bind(this);
this.handleContextMenuSelected = this.handleContextMenuSelected.bind(this);
this.handleContextMenuClosed = this.handleContextMenuClosed.bind(this);
const showContextMenu =
props.source === 'dashboard' &&
isFeatureEnabled(FeatureFlag.DRILL_TO_DETAIL);
this.hooks = {
onAddFilter: this.handleAddFilter,
onContextMenu: showContextMenu ? this.handleOnContextMenu : undefined,
onError: this.handleRenderFailure,
setControlValue: this.handleSetControlValue,
onFilterMenuOpen: this.props.onFilterMenuOpen,
@@ -92,13 +113,16 @@ class ChartRenderer extends React.Component {
};
}
shouldComponentUpdate(nextProps) {
shouldComponentUpdate(nextProps, nextState) {
const resultsReady =
nextProps.queriesResponse &&
['success', 'rendered'].indexOf(nextProps.chartStatus) > -1 &&
!nextProps.queriesResponse?.[0]?.error;
if (resultsReady) {
if (!isEqual(this.state, nextState)) {
return true;
}
this.hasQueryResponseChange =
nextProps.queriesResponse !== this.props.queriesResponse;
return (
@@ -172,6 +196,22 @@ class ChartRenderer extends React.Component {
}
}
handleOnContextMenu(filters, offsetX, offsetY) {
this.contextMenuRef.current.open(filters, offsetX, offsetY);
this.setState({ inContextMenu: true });
}
handleContextMenuSelected(filters) {
const extraFilters = this.props.formData.extra_form_data?.filters || [];
// eslint-disable-next-line no-alert
alert(JSON.stringify(filters.concat(extraFilters)));
this.setState({ inContextMenu: false });
}
handleContextMenuClosed() {
this.setState({ inContextMenu: false });
}
render() {
const { chartAlert, chartStatus, chartId } = this.props;
@@ -247,28 +287,39 @@ class ChartRenderer extends React.Component {
}
return (
<SuperChart
disableErrorBoundary
key={`${chartId}${webpackHash}`}
id={`chart-id-${chartId}`}
className={chartClassName}
chartType={vizType}
width={width}
height={height}
annotationData={annotationData}
datasource={datasource}
initialValues={initialValues}
formData={currentFormData}
ownState={ownState}
filterState={filterState}
hooks={this.hooks}
behaviors={behaviors}
queriesData={queriesResponse}
onRenderSuccess={this.handleRenderSuccess}
onRenderFailure={this.handleRenderFailure}
noResults={noResultsComponent}
postTransformProps={postTransformProps}
/>
<div>
{this.props.source === 'dashboard' && (
<ChartContextMenu
ref={this.contextMenuRef}
id={chartId}
onSelection={this.handleContextMenuSelected}
onClose={this.handleContextMenuClosed}
/>
)}
<SuperChart
disableErrorBoundary
key={`${chartId}${webpackHash}`}
id={`chart-id-${chartId}`}
className={chartClassName}
chartType={vizType}
width={width}
height={height}
annotationData={annotationData}
datasource={datasource}
initialValues={initialValues}
formData={currentFormData}
ownState={ownState}
filterState={filterState}
hooks={this.hooks}
behaviors={behaviors}
queriesData={queriesResponse}
onRenderSuccess={this.handleRenderSuccess}
onRenderFailure={this.handleRenderFailure}
noResults={noResultsComponent}
postTransformProps={postTransformProps}
inContextMenu={this.state.inContextMenu}
/>
</div>
);
}
}