diff --git a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.jsx b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.jsx
index f04e3db5fb6dc..68418ad03b187 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.jsx
+++ b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.jsx
@@ -81,6 +81,7 @@ class MapBox extends React.Component {
this.handleViewportChange = this.handleViewportChange.bind(this);
this.zoomIn = this.zoomIn.bind(this);
this.zoomOut = this.zoomOut.bind(this);
+ this.handleViewDetail = this.handleViewDetail.bind(this);
}
zoomIn() {
@@ -107,6 +108,35 @@ class MapBox extends React.Component {
onViewportChange(viewport);
}
+ handleViewDetail(value) {
+ const dataMask = {
+ id: this.props?.filterIdForDetails,
+ extraFormData: {
+ filters: [
+ {
+ col: 'hospital_name',
+ op: 'IN',
+ val: [value],
+ },
+ ],
+ },
+ filterState: {
+ validateMessage: false,
+ label: value,
+ value: [value],
+ },
+ ownState: {},
+ };
+
+ this?.props?.onChangeParentTab(4);
+ this?.props?.handleApply(dataMask, this.props?.filterIdForDetails, () => {
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth',
+ });
+ });
+ }
+
render() {
const {
width,
@@ -181,6 +211,7 @@ class MapBox extends React.Component {
namesDisappearZoomLevel={namesDisappearZoomLevel}
globalOpacity={globalOpacity}
compositeOperation="screen"
+ handleViewDetail={this.handleViewDetail}
renderWhileDragging={renderWhileDragging}
aggregation={hasCustomMetric ? aggregatorName : null}
lngLatAccessor={location => {
diff --git a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.jsx b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.jsx
index df48f0d884cae..5326136f34243 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.jsx
+++ b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.jsx
@@ -276,7 +276,9 @@ class ScatterPlotGlowOverlay extends React.PureComponent {
diff --git a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/controlPanel.ts b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/controlPanel.ts
index 2865811678b6f..a447a4b3c4d52 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/controlPanel.ts
+++ b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/controlPanel.ts
@@ -75,6 +75,20 @@ const config: ControlPanelConfig = {
},
},
],
+ [
+ {
+ name: 'filterIdForDetails',
+ config: {
+ type: 'TextControl',
+ label: t('Filter ID for item details'),
+ default: '',
+ isFloat: false,
+ description: t(
+ 'Filter id for item details. Which will take us to the details tab',
+ ),
+ },
+ },
+ ],
],
},
{
diff --git a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/transformProps.js b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/transformProps.js
index 13ef13ee77914..269a1c01c0757 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-map-box/src/transformProps.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-map-box/src/transformProps.js
@@ -36,6 +36,7 @@ export default function transformProps(chartProps) {
pointRadiusUnit,
renderWhileDragging,
namesDisappearZoomLevel,
+ filterIdForDetails,
} = formData;
// Validate mapbox color
@@ -96,5 +97,8 @@ export default function transformProps(chartProps) {
renderWhileDragging,
rgb,
namesDisappearZoomLevel,
+ filterIdForDetails,
+ onChangeParentTab: hooks?.onChangeParentTab,
+ handleApply: hooks?.handleApply,
};
}
diff --git a/superset-frontend/src/components/Chart/ChartRenderer.jsx b/superset-frontend/src/components/Chart/ChartRenderer.jsx
index 5f29840dde898..d542d298ee3ae 100644
--- a/superset-frontend/src/components/Chart/ChartRenderer.jsx
+++ b/superset-frontend/src/components/Chart/ChartRenderer.jsx
@@ -119,6 +119,8 @@ class ChartRenderer extends React.Component {
setDataMask: dataMask => {
this.props.actions?.updateDataMask(this.props.chartId, dataMask);
},
+ onChangeParentTab: this.props?.onChangeParentTab,
+ handleApply: this.props?.handleApply,
};
// TODO: queriesResponse comes from Redux store but it's being edited by
diff --git a/superset-frontend/src/dashboard/components/DashboardGrid.jsx b/superset-frontend/src/dashboard/components/DashboardGrid.jsx
index 6509596304779..481c3854b8715 100644
--- a/superset-frontend/src/dashboard/components/DashboardGrid.jsx
+++ b/superset-frontend/src/dashboard/components/DashboardGrid.jsx
@@ -313,6 +313,7 @@ class DashboardGrid extends React.PureComponent {
onResize={this.handleResize}
onResizeStop={this.handleResizeStop}
onChangeTab={this.handleChangeTab}
+ onChangeParentTab={this.props?.onChangeParentTab}
isCurrentPartChartsLoading={isCurrentPartChartsLoading}
/>
{/* make the area below components droppable */}
diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
index aee061955f1f9..b088034db68c2 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
@@ -415,6 +415,8 @@ class Chart extends React.Component {
isInView,
emitCrossFilters,
logEvent,
+ onChangeParentTab,
+ handleApply,
} = this.props;
const { width } = this.state;
@@ -530,6 +532,8 @@ class Chart extends React.Component {
postTransformProps={postTransformProps}
datasetsStatus={datasetsStatus}
isInView={isInView}
+ handleApply={handleApply}
+ onChangeParentTab={onChangeParentTab}
emitCrossFilters={emitCrossFilters}
/>
diff --git a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.tsx b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.tsx
index bcc58d0691dab..ab39f1dc356cc 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.tsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable import/no-unresolved */
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -19,8 +20,9 @@
import React, { useState, useMemo, useCallback, useEffect } from 'react';
import { ResizeCallback, ResizeStartCallback } from 're-resizable';
import cx from 'classnames';
-import { useSelector } from 'react-redux';
-import { css } from '@superset-ui/core';
+import { useDispatch, useSelector } from 'react-redux';
+import { updateDataMask } from 'src/dataMask/actions';
+import { css, DataMask, DataMaskStateWithId } from '@superset-ui/core';
import { LayoutItem, RootState } from 'src/dashboard/types';
import AnchorLink from 'src/dashboard/components/AnchorLink';
import Chart from 'src/dashboard/containers/Chart';
@@ -37,6 +39,9 @@ import {
GRID_MIN_COLUMN_COUNT,
GRID_MIN_ROW_UNITS,
} from 'src/dashboard/util/constants';
+import { logEvent } from 'src/logger/actions';
+import { LOG_ACTIONS_CHANGE_DASHBOARD_FILTER } from 'src/logger/LogUtils';
+import { useNativeFiltersDataMask } from '../nativeFilters/FilterBar/state';
export const CHART_MARGIN = 32;
@@ -47,6 +52,7 @@ interface ChartHolderProps {
component: LayoutItem;
parentComponent: LayoutItem;
getComponentById?: (id?: string) => LayoutItem | undefined;
+ onChangeParentTab?: (tabIndex: number) => void;
index: number;
depth: number;
editMode: boolean;
@@ -100,10 +106,35 @@ const ChartHolder: React.FC = ({
handleComponentDrop,
setFullSizeChartId,
isInView,
+ onChangeParentTab,
}) => {
+ const dispatch = useDispatch();
const { chartId } = component.meta;
const isFullSize = fullSizeChartId === chartId;
+ const dataMaskApplied: DataMaskStateWithId = useNativeFiltersDataMask();
+
+ const handleApply = useCallback(
+ async (
+ dataMask: DataMask,
+ filterIdForDetails: string,
+ callback: () => void,
+ ) => {
+ if (dataMask && filterIdForDetails) {
+ dispatch(logEvent(LOG_ACTIONS_CHANGE_DASHBOARD_FILTER, {}));
+
+ if (dataMaskApplied[filterIdForDetails]) {
+ await dispatch(updateDataMask(filterIdForDetails, dataMask));
+ }
+
+ if (callback) {
+ callback();
+ }
+ }
+ },
+ [dataMaskApplied, dispatch],
+ );
+
const focusHighlightStyles = useFilterFocusHighlightStyles(chartId);
const dashboardState = useSelector(
(state: RootState) => state.dashboardState,
@@ -315,6 +346,8 @@ const ChartHolder: React.FC = ({
setControlValue={handleExtraControl}
extraControls={extraControls}
isInView={isInView}
+ onChangeParentTab={onChangeParentTab}
+ handleApply={handleApply}
/>
{editMode && (
diff --git a/superset-frontend/src/dashboard/components/gridComponents/Column.jsx b/superset-frontend/src/dashboard/components/gridComponents/Column.jsx
index 98f2b84e8d920..45c6af350b5f6 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Column.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Column.jsx
@@ -280,6 +280,7 @@ class Column extends React.PureComponent {
onResizeStop={onResizeStop}
isComponentVisible={isComponentVisible}
onChangeTab={onChangeTab}
+ onChangeParentTab={this.props?.onChangeParentTab}
/>
{editMode && (
{editMode && (
diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx
index fa72d8ea5a6ba..8549a2ad0f78f 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx
@@ -183,6 +183,7 @@ class Tab extends React.PureComponent {
setEditMode,
dashboardId,
isChild,
+ onChangeParentTab,
} = this.props;
const shouldDisplayEmptyState = tabComponent.children.length === 0;
@@ -263,6 +264,7 @@ class Tab extends React.PureComponent {
onResizeStop={onResizeStop}
isComponentVisible={isComponentVisible}
onChangeTab={this.handleChangeTab}
+ onChangeParentTab={onChangeParentTab}
/>
{/* Make bottom of tab droppable */}
{editMode && (
diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx
index 9cff499c84e44..bf0527d5ba712 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx
@@ -357,6 +357,7 @@ export class Tabs extends React.PureComponent {
nativeFilters,
isChild,
isCurrentPartChartsLoading,
+ onChangeParentTab,
} = this.props;
const { children: tabIds } = tabsComponent;
@@ -436,6 +437,9 @@ export class Tabs extends React.PureComponent {
onHoverTab={() => this.handleClickTab(tabIndex)}
isFocused={activeKey === tabId}
isChild={isChild}
+ onChangeParentTab={
+ isChild ? onChangeParentTab : this.handleClickTab
+ }
isHighlighted={
activeKey !== tabId && tabsToHighlight?.includes(tabId)
}
@@ -449,6 +453,9 @@ export class Tabs extends React.PureComponent {
parentId={tabsComponent.id}
depth={depth} // see isValidChild.js for why tabs don't increment child depth
index={tabIndex}
+ onChangeParentTab={
+ isChild ? onChangeParentTab : this.handleClickTab
+ }
isCurrentPartChartsLoading={isCurrentPartChartsLoading}
renderType={RENDER_TAB_CONTENT}
availableColumnCount={availableColumnCount}
diff --git a/superset-frontend/src/dashboard/containers/Chart.jsx b/superset-frontend/src/dashboard/containers/Chart.jsx
index 1e50602b06299..6fd24fcb6fa9f 100644
--- a/superset-frontend/src/dashboard/containers/Chart.jsx
+++ b/superset-frontend/src/dashboard/containers/Chart.jsx
@@ -54,7 +54,8 @@ function mapStateToProps(
},
ownProps,
) {
- const { id, extraControls, setControlValue } = ownProps;
+ const { id, extraControls, setControlValue, onChangeParentTab, handleApply } =
+ ownProps;
const chart = chartQueries[id] || EMPTY_OBJECT;
const datasource =
(chart && chart.form_data && datasources[chart.form_data.datasource]) ||
@@ -101,6 +102,8 @@ function mapStateToProps(
setControlValue,
datasetsStatus,
emitCrossFilters: !!dashboardInfo.crossFiltersEnabled,
+ onChangeParentTab,
+ handleApply,
};
}