diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts index b7ac546993783..c5bb99ed22c57 100644 --- a/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts @@ -126,6 +126,7 @@ export type NativeFiltersState = { filters: Filters; filterSets: FilterSets; focusedFilterId?: string; + hoveredFilterId?: string; }; export type DashboardComponentMetadata = { diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts b/superset-frontend/src/dashboard/actions/nativeFilters.ts index 71cc01d99681f..76ac6cc1fbede 100644 --- a/superset-frontend/src/dashboard/actions/nativeFilters.ts +++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts @@ -372,6 +372,28 @@ export function unsetFocusedNativeFilter(): UnsetFocusedNativeFilter { }; } +export const SET_HOVERED_NATIVE_FILTER = 'SET_HOVERED_NATIVE_FILTER'; +export interface SetHoveredNativeFilter { + type: typeof SET_HOVERED_NATIVE_FILTER; + id: string; +} +export const UNSET_HOVERED_NATIVE_FILTER = 'UNSET_HOVERED_NATIVE_FILTER'; +export interface UnsetHoveredNativeFilter { + type: typeof UNSET_HOVERED_NATIVE_FILTER; +} + +export function setHoveredNativeFilter(id: string): SetHoveredNativeFilter { + return { + type: SET_HOVERED_NATIVE_FILTER, + id, + }; +} +export function unsetHoveredNativeFilter(): UnsetHoveredNativeFilter { + return { + type: UNSET_HOVERED_NATIVE_FILTER, + }; +} + export type AnyFilterAction = | SetFilterConfigBegin | SetFilterConfigComplete @@ -383,6 +405,8 @@ export type AnyFilterAction = | SetBootstrapData | SetFocusedNativeFilter | UnsetFocusedNativeFilter + | SetHoveredNativeFilter + | UnsetHoveredNativeFilter | CreateFilterSetBegin | CreateFilterSetComplete | CreateFilterSetFail diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index fdece196d09ce..4a318a42abd49 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -239,9 +239,8 @@ const DashboardBuilder: FC = () => { const canEdit = useSelector( ({ dashboardInfo }) => dashboardInfo.dash_edit_perm, ); - const directPathToChild = useSelector( - state => state.dashboardState.directPathToChild, - ); + const nativeFilters = useSelector((state: RootState) => state.nativeFilters); + const focusedFilterId = nativeFilters?.focusedFilterId; const fullSizeChartId = useSelector( state => state.dashboardState.fullSizeChartId, ); @@ -369,7 +368,7 @@ const DashboardBuilder: FC = () => { {showFilterBar && filterBarOrientation === FilterBarOrientation.HORIZONTAL && ( )} @@ -401,7 +400,7 @@ const DashboardBuilder: FC = () => { ), [ - directPathToChild, + focusedFilterId, nativeFiltersEnabled, filterBarOrientation, editMode, @@ -437,7 +436,7 @@ const DashboardBuilder: FC = () => { { const onHighlightFilterSource = useCallback( (path: string[]) => { - dispatch(setDirectPathToChild(path)); + dispatch(setFocusedNativeFilter(path[0])); }, [dispatch], ); diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx index 5f4e6f5150276..2588ce59100e8 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx @@ -340,9 +340,10 @@ export class Tabs extends React.PureComponent { const { tabIndex: selectedTabIndex, activeKey } = this.state; let tabsToHighlight; - if (nativeFilters?.focusedFilterId) { - tabsToHighlight = - nativeFilters.filters[nativeFilters.focusedFilterId].tabsInScope; + const highlightedFilterId = + nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId; + if (highlightedFilterId) { + tabsToHighlight = nativeFilters.filters[highlightedFilterId]?.tabsInScope; } return ( void; }; const FilterControls: FC = ({ - directPathToChild, + focusedFilterId, dataMaskSelected, onFilterSelectionChange, }) => { @@ -65,10 +74,11 @@ const FilterControls: FC = ({ ); const [overflowedIds, setOverflowedIds] = useState([]); + const popoverRef = useRef(null); const { filterControlFactory, filtersWithValues } = useFilterControlFactory( dataMaskSelected, - directPathToChild, + focusedFilterId, onFilterSelectionChange, ); const portalNodes = useMemo(() => { @@ -183,6 +193,7 @@ const FilterControls: FC = ({ ) : undefined } + ref={popoverRef} onOverflowingStateChange={({ overflowed: nextOverflowedIds }) => { if ( nextOverflowedIds.length !== overflowedIds.length || @@ -211,6 +222,12 @@ const FilterControls: FC = ({ ); }, [filtersOutOfScope, filtersWithValues, overflowedFiltersInScope]); + useEffect(() => { + if (focusedFilterId && overflowedIds.includes(focusedFilterId)) { + popoverRef?.current?.open(); + } + }, [focusedFilterId, popoverRef, overflowedIds]); + return ( <> {portalNodes diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx index a08200d83b217..fbffcd2bc5367 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx @@ -44,7 +44,8 @@ import { waitForAsyncData } from 'src/middleware/asyncEvent'; import { ClientErrorObject } from 'src/utils/getClientErrorObject'; import { FilterBarOrientation, RootState } from 'src/dashboard/types'; import { onFiltersRefreshSuccess } from 'src/dashboard/actions/dashboardState'; -import { dispatchFocusAction } from './utils'; +import { FAST_DEBOUNCE } from 'src/constants'; +import { dispatchHoverAction, dispatchFocusAction } from './utils'; import { FilterControlProps } from './types'; import { getFormData } from '../../utils'; import { useFilterDependencies } from './state'; @@ -78,7 +79,7 @@ const useShouldFilterRefresh = () => { const FilterValue: React.FC = ({ dataMaskSelected, filter, - directPathToChild, + focusedFilterId, onFilterSelectionChange, inView = true, showOverflow, @@ -211,10 +212,12 @@ const FilterValue: React.FC = ({ ]); useEffect(() => { - if (directPathToChild?.[0] === filter.id) { - inputRef?.current?.focus(); + if (focusedFilterId && focusedFilterId === filter.id) { + setTimeout(() => { + inputRef?.current?.focus(); + }, FAST_DEBOUNCE); } - }, [inputRef, directPathToChild, filter.id]); + }, [inputRef, focusedFilterId, filter.id]); const setDataMask = useCallback( (dataMask: DataMask) => onFilterSelectionChange(filter, dataMask), @@ -230,14 +233,32 @@ const FilterValue: React.FC = ({ [dispatch], ); + const setHoveredFilter = useCallback( + () => dispatchHoverAction(dispatch, id), + [dispatch, id], + ); + const unsetHoveredFilter = useCallback( + () => dispatchHoverAction(dispatch), + [dispatch], + ); + const hooks = useMemo( () => ({ setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, }), - [setDataMask, setFilterActive, setFocusedFilter, unsetFocusedFilter], + [ + setDataMask, + setFilterActive, + setHoveredFilter, + unsetHoveredFilter, + setFocusedFilter, + unsetFocusedFilter, + ], ); const isMissingRequiredValue = checkIsMissingRequiredValue( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts index a48ca5f0aab6f..ac9cca8c01799 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts @@ -36,7 +36,7 @@ export interface FilterControlProps extends BaseFilterProps { dataMask?: DataMask; }; icon?: React.ReactElement; - directPathToChild?: string[]; + focusedFilterId?: string; onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void; inView?: boolean; showOverflow?: boolean; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts index 3077c42768e84..5e0e159d1189d 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts @@ -21,7 +21,21 @@ import { Dispatch } from 'react'; import { setFocusedNativeFilter, unsetFocusedNativeFilter, + setHoveredNativeFilter, + unsetHoveredNativeFilter, } from 'src/dashboard/actions/nativeFilters'; +import { FAST_DEBOUNCE } from 'src/constants'; + +export const dispatchHoverAction = debounce( + (dispatch: Dispatch, id?: string) => { + if (id) { + dispatch(setHoveredNativeFilter(id)); + } else { + dispatch(unsetHoveredNativeFilter()); + } + }, + FAST_DEBOUNCE, +); export const dispatchFocusAction = debounce( (dispatch: Dispatch, id?: string) => { @@ -31,5 +45,5 @@ export const dispatchFocusAction = debounce( dispatch(unsetFocusedNativeFilter()); } }, - 300, + FAST_DEBOUNCE, ); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Horizontal.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Horizontal.tsx index d085e08900052..d640236ea831f 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Horizontal.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Horizontal.tsx @@ -93,7 +93,7 @@ const HorizontalFilterBar: React.FC = ({ dataMaskSelected, filterValues, isInitialized, - directPathToChild, + focusedFilterId, onSelectionChange, }) => { const hasFilters = filterValues.length > 0; @@ -124,7 +124,7 @@ const HorizontalFilterBar: React.FC = ({ {hasFilters && ( )} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx index 54ec436ea4cbc..2a6b7178362d1 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx @@ -141,7 +141,7 @@ const VerticalFilterBar: React.FC = ({ actions, canEdit, dataMaskSelected, - directPathToChild, + focusedFilterId, filtersOpen, filterValues, height, @@ -258,7 +258,7 @@ const VerticalFilterBar: React.FC = ({ @@ -300,7 +300,7 @@ const VerticalFilterBar: React.FC = ({ diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx index 2905c6a075acf..6eeee2ae708f9 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx @@ -111,7 +111,7 @@ const publishDataMask = debounce( export const FilterBarScrollContext = createContext(false); const FilterBar: React.FC = ({ - directPathToChild, + focusedFilterId, orientation = FilterBarOrientation.VERTICAL, verticalConfig, }) => { @@ -254,7 +254,7 @@ const FilterBar: React.FC = ({ canEdit={canEdit} dashboardId={dashboardId} dataMaskSelected={dataMaskSelected} - directPathToChild={directPathToChild} + focusedFilterId={focusedFilterId} filterValues={filterValues} isInitialized={isInitialized} onSelectionChange={handleFilterSelectionChange} @@ -264,7 +264,7 @@ const FilterBar: React.FC = ({ actions={actions} canEdit={canEdit} dataMaskSelected={dataMaskSelected} - directPathToChild={directPathToChild} + focusedFilterId={focusedFilterId} filtersOpen={verticalConfig.filtersOpen} filterValues={filterValues} isInitialized={isInitialized} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts index ae1368eff83d6..034a639f589e0 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts @@ -28,7 +28,7 @@ interface CommonFiltersBarProps { actions: React.ReactNode; canEdit: boolean; dataMaskSelected: DataMaskStateWithId; - directPathToChild?: string[]; + focusedFilterId?: string; filterValues: (Filter | Divider)[]; isInitialized: boolean; onSelectionChange: ( @@ -46,7 +46,7 @@ interface VerticalBarConfig { } export interface FiltersBarProps - extends Pick { + extends Pick { orientation: FilterBarOrientation; verticalConfig?: VerticalBarConfig; } diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/useFilterControlFactory.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/useFilterControlFactory.tsx index 6893e629cb49c..80e532e45e258 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/useFilterControlFactory.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/useFilterControlFactory.tsx @@ -33,7 +33,7 @@ import FilterDivider from './FilterControls/FilterDivider'; export const useFilterControlFactory = ( dataMaskSelected: DataMaskStateWithId, - directPathToChild: string[] | undefined, + focusedFilterId: string | undefined, onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void, ) => { const filters = useFilters(); @@ -68,7 +68,7 @@ export const useFilterControlFactory = ( { const dispatch = useDispatch(); const handleClick = useCallback(() => { - dispatch(setDirectPathToChild([dependency.id])); + dispatch(setFocusedNativeFilter(dependency.id)); }, [dependency.id, dispatch]); return ( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/FilterCard.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/FilterCard.test.tsx index 93f1ccfca438d..970d494ebdbec 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/FilterCard.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/FilterCard.test.tsx @@ -23,7 +23,7 @@ import { Filter, NativeFilterType } from '@superset-ui/core'; import userEvent from '@testing-library/user-event'; import { render, screen } from 'spec/helpers/testing-library'; import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants'; -import { SET_DIRECT_PATH } from 'src/dashboard/actions/dashboardState'; +import { SET_FOCUSED_NATIVE_FILTER } from 'src/dashboard/actions/nativeFilters'; import { FilterCardContent } from './FilterCardContent'; const baseInitialState = { @@ -298,8 +298,8 @@ describe('Filter Card', () => { userEvent.click(screen.getByText('Native filter 2')); expect(dummyDispatch).toHaveBeenCalledWith({ - type: SET_DIRECT_PATH, - path: ['NATIVE_FILTER-2'], + type: SET_FOCUSED_NATIVE_FILTER, + id: 'NATIVE_FILTER-2', }); }); }); diff --git a/superset-frontend/src/dashboard/reducers/nativeFilters.ts b/superset-frontend/src/dashboard/reducers/nativeFilters.ts index b3900af31cf52..81a1a4bd2d208 100644 --- a/superset-frontend/src/dashboard/reducers/nativeFilters.ts +++ b/superset-frontend/src/dashboard/reducers/nativeFilters.ts @@ -23,6 +23,8 @@ import { SET_FILTER_SETS_COMPLETE, SET_FOCUSED_NATIVE_FILTER, UNSET_FOCUSED_NATIVE_FILTER, + SET_HOVERED_NATIVE_FILTER, + UNSET_HOVERED_NATIVE_FILTER, } from 'src/dashboard/actions/nativeFilters'; import { FilterSet, @@ -102,6 +104,18 @@ export default function nativeFilterReducer( ...state, focusedFilterId: undefined, }; + + case SET_HOVERED_NATIVE_FILTER: + return { + ...state, + hoveredFilterId: action.id, + }; + + case UNSET_HOVERED_NATIVE_FILTER: + return { + ...state, + hoveredFilterId: undefined, + }; // TODO handle SET_FILTER_CONFIG_FAIL action default: return state; diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx index 1d4d5af367b01..fdc31f78af52e 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx @@ -79,6 +79,25 @@ describe('useFilterFocusHighlightStyles', () => { expect(parseFloat(styles.opacity)).toBe(0.3); }); + it('should return unfocused styles if chart is not in scope of hovered native filter', async () => { + const store = createMockStore({ + nativeFilters: { + hoveredFilterId: 'test-filter', + filters: { + otherId: { + chartsInScope: [], + }, + }, + }, + }); + renderWrapper(10, store); + + const container = screen.getByTestId('test-component'); + + const styles = getComputedStyle(container); + expect(parseFloat(styles.opacity)).toBe(0.3); + }); + it('should return focused styles if chart is in scope of focused native filter', async () => { const chartId = 18; const store = createMockStore({ @@ -99,6 +118,26 @@ describe('useFilterFocusHighlightStyles', () => { expect(parseFloat(styles.opacity)).toBe(1); }); + it('should return focused styles if chart is in scope of hovered native filter', async () => { + const chartId = 18; + const store = createMockStore({ + nativeFilters: { + hoveredFilterId: 'testFilter', + filters: { + testFilter: { + chartsInScope: [chartId], + }, + }, + }, + }); + renderWrapper(chartId, store); + + const container = screen.getByTestId('test-component'); + + const styles = getComputedStyle(container); + expect(parseFloat(styles.opacity)).toBe(1); + }); + it('should return unfocused styles if focusedFilterField is targeting a different chart', async () => { const chartId = 18; const store = createMockStore({ diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts index 958dce57fc6f1..8be43490ad3aa 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts @@ -49,8 +49,9 @@ const useFilterFocusHighlightStyles = (chartId: number) => { dashboardFilters, ); - const focusedNativeFilterId = nativeFilters.focusedFilterId; - if (!(focusedFilterScope || focusedNativeFilterId)) { + const highlightedFilterId = + nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId; + if (!(focusedFilterScope || highlightedFilterId)) { return {}; } @@ -67,9 +68,9 @@ const useFilterFocusHighlightStyles = (chartId: number) => { pointerEvents: 'auto', }; - if (focusedNativeFilterId) { + if (highlightedFilterId) { if ( - nativeFilters.filters[focusedNativeFilterId]?.chartsInScope?.includes( + nativeFilters.filters[highlightedFilterId]?.chartsInScope?.includes( chartId, ) ) { diff --git a/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx b/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx index 091232a5ec3e6..dfc314024ec9f 100644 --- a/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx @@ -36,6 +36,8 @@ export default function PluginFilterGroupBy(props: PluginFilterGroupByProps) { height, width, setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, @@ -116,6 +118,8 @@ export default function PluginFilterGroupBy(props: PluginFilterGroupByProps) { onChange={handleChange} onBlur={unsetFocusedFilter} onFocus={setFocusedFilter} + onMouseEnter={setHoveredFilter} + onMouseLeave={unsetHoveredFilter} ref={inputRef} options={options} onDropdownVisibleChange={setFilterActive} diff --git a/superset-frontend/src/filters/components/GroupBy/transformProps.ts b/superset-frontend/src/filters/components/GroupBy/transformProps.ts index 9ca0ec047bfa8..1f502602734eb 100644 --- a/superset-frontend/src/filters/components/GroupBy/transformProps.ts +++ b/superset-frontend/src/filters/components/GroupBy/transformProps.ts @@ -33,6 +33,8 @@ export default function transformProps(chartProps: ChartProps) { } = chartProps; const { setDataMask = noOp, + setHoveredFilter = noOp, + unsetHoveredFilter = noOp, setFocusedFilter = noOp, unsetFocusedFilter = noOp, setFilterActive = noOp, @@ -48,6 +50,8 @@ export default function transformProps(chartProps: ChartProps) { data, formData: { ...DEFAULT_FORM_DATA, ...formData }, setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, diff --git a/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx b/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx index f3673f223ee2c..1f8ea48206f0e 100644 --- a/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx @@ -152,6 +152,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) { setDataMask, setFocusedFilter, unsetFocusedFilter, + setHoveredFilter, + unsetHoveredFilter, setFilterActive, filterState, inputRef, @@ -289,8 +291,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) { validateStatus={filterState.validateStatus} onFocus={setFocusedFilter} onBlur={unsetFocusedFilter} - onMouseEnter={setFocusedFilter} - onMouseLeave={unsetFocusedFilter} + onMouseEnter={setHoveredFilter} + onMouseLeave={unsetHoveredFilter} onMouseDown={() => setFilterActive(true)} onMouseUp={() => setFilterActive(false)} > diff --git a/superset-frontend/src/filters/components/Range/transformProps.ts b/superset-frontend/src/filters/components/Range/transformProps.ts index f4c47cec267b1..370b7dccd4f57 100644 --- a/superset-frontend/src/filters/components/Range/transformProps.ts +++ b/superset-frontend/src/filters/components/Range/transformProps.ts @@ -34,6 +34,8 @@ export default function transformProps(chartProps: ChartProps) { setDataMask = noOp, setFocusedFilter = noOp, unsetFocusedFilter = noOp, + setHoveredFilter = noOp, + unsetHoveredFilter = noOp, setFilterActive = noOp, } = hooks; const { data } = queriesData[0]; @@ -46,6 +48,8 @@ export default function transformProps(chartProps: ChartProps) { setDataMask, filterState, width, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx index 9cea856d47901..52dbaf108e0a8 100644 --- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx @@ -82,6 +82,8 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) { isRefreshing, width, setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, @@ -317,8 +319,9 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) { onSearch={searchWrapper} onSelect={clearSuggestionSearch} onBlur={handleBlur} - onMouseEnter={setFocusedFilter} - onMouseLeave={unsetFocusedFilter} + onFocus={setFocusedFilter} + onMouseEnter={setHoveredFilter} + onMouseLeave={unsetHoveredFilter} // @ts-ignore onChange={handleChange} ref={inputRef} diff --git a/superset-frontend/src/filters/components/Select/transformProps.ts b/superset-frontend/src/filters/components/Select/transformProps.ts index 59d9adc57e930..666d937e43488 100644 --- a/superset-frontend/src/filters/components/Select/transformProps.ts +++ b/superset-frontend/src/filters/components/Select/transformProps.ts @@ -38,6 +38,8 @@ export default function transformProps( const newFormData = { ...DEFAULT_FORM_DATA, ...formData }; const { setDataMask = noOp, + setHoveredFilter = noOp, + unsetHoveredFilter = noOp, setFocusedFilter = noOp, unsetFocusedFilter = noOp, setFilterActive = noOp, @@ -60,6 +62,8 @@ export default function transformProps( formData: newFormData, isRefreshing, setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, diff --git a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx index 82bfc678f0a7e..1d45ba28af57e 100644 --- a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx @@ -57,6 +57,8 @@ const ControlContainer = styled.div<{ export default function TimeFilterPlugin(props: PluginFilterTimeProps) { const { setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, @@ -95,8 +97,8 @@ export default function TimeFilterPlugin(props: PluginFilterTimeProps) { validateStatus={filterState.validateStatus} onFocus={setFocusedFilter} onBlur={unsetFocusedFilter} - onMouseEnter={setFocusedFilter} - onMouseLeave={unsetFocusedFilter} + onMouseEnter={setHoveredFilter} + onMouseLeave={unsetHoveredFilter} > void; unsetFocusedFilter: () => void; + setHoveredFilter: () => void; + unsetHoveredFilter: () => void; setFilterActive: (isActive: boolean) => void; }