From df91664217b5369d1f742ce03596a366e18cd4b9 Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Fri, 2 Dec 2022 15:03:01 +0200 Subject: [PATCH] feat: Programmatically open "more filters" dropdown in Horizontal Filter Bar (#22276) Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com> --- .../src/query/types/Dashboard.ts | 1 + .../src/dashboard/actions/nativeFilters.ts | 24 ++++++++++++ .../DashboardBuilder/DashboardBuilder.tsx | 11 +++--- .../components/FiltersBadge/index.tsx | 4 +- .../components/gridComponents/Tabs.jsx | 7 ++-- .../FilterControls/FilterControl.tsx | 4 +- .../FilterControls/FilterControls.tsx | 27 ++++++++++--- .../FilterBar/FilterControls/FilterValue.tsx | 33 +++++++++++++--- .../FilterBar/FilterControls/types.ts | 2 +- .../FilterBar/FilterControls/utils.ts | 16 +++++++- .../nativeFilters/FilterBar/Horizontal.tsx | 4 +- .../nativeFilters/FilterBar/Vertical.tsx | 6 +-- .../nativeFilters/FilterBar/index.tsx | 6 +-- .../nativeFilters/FilterBar/types.ts | 4 +- .../FilterBar/useFilterControlFactory.tsx | 6 +-- .../FilterCard/DependenciesRow.tsx | 4 +- .../FilterCard/FilterCard.test.tsx | 6 +-- .../src/dashboard/reducers/nativeFilters.ts | 14 +++++++ .../useFilterFocusHighlightStyles.test.tsx | 39 +++++++++++++++++++ .../util/useFilterFocusHighlightStyles.ts | 9 +++-- .../GroupBy/GroupByFilterPlugin.tsx | 4 ++ .../components/GroupBy/transformProps.ts | 4 ++ .../components/Range/RangeFilterPlugin.tsx | 6 ++- .../components/Range/transformProps.ts | 4 ++ .../components/Select/SelectFilterPlugin.tsx | 7 +++- .../components/Select/transformProps.ts | 4 ++ .../components/Time/TimeFilterPlugin.tsx | 6 ++- .../filters/components/Time/transformProps.ts | 4 ++ .../TimeColumn/TimeColumnFilterPlugin.tsx | 8 +++- .../components/TimeColumn/transformProps.ts | 4 ++ .../TimeGrain/TimeGrainFilterPlugin.tsx | 8 +++- .../components/TimeGrain/transformProps.ts | 4 ++ .../src/filters/components/types.ts | 2 + 33 files changed, 234 insertions(+), 58 deletions(-) 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 b7ac546993..c5bb99ed22 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 71cc01d996..76ac6cc1fb 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 fdece196d0..4a318a42ab 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 5f4e6f5150..2588ce5910 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 5cc9d804e1..213329c4b3 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 a48ca5f0aa..ac9cca8c01 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 3077c42768..5e0e159d11 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 d085e08900..d640236ea8 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 54ec436ea4..2a6b717836 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 2905c6a075..6eeee2ae70 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 ae1368eff8..034a639f58 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 6893e629cb..80e532e45e 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 93f1ccfca4..970d494ebd 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 b3900af31c..81a1a4bd2d 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 1d4d5af367..fdc31f78af 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 958dce57fc..8be43490ad 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 091232a5ec..dfc314024e 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 9ca0ec047b..1f50260273 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 9c60e60814..5c8533dd1e 100644 --- a/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx @@ -171,6 +171,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) { setDataMask, setFocusedFilter, unsetFocusedFilter, + setHoveredFilter, + unsetHoveredFilter, setFilterActive, filterState, inputRef, @@ -312,8 +314,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) { isOverflowing={isOverflowingFilterBar} 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 48def72cad..cbca7a982a 100644 --- a/superset-frontend/src/filters/components/Range/transformProps.ts +++ b/superset-frontend/src/filters/components/Range/transformProps.ts @@ -35,6 +35,8 @@ export default function transformProps(chartProps: ChartProps) { setDataMask = noOp, setFocusedFilter = noOp, unsetFocusedFilter = noOp, + setHoveredFilter = noOp, + unsetHoveredFilter = noOp, setFilterActive = noOp, } = hooks; const { data } = queriesData[0]; @@ -47,6 +49,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 7337f51689..c19754b518 100644 --- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx @@ -83,6 +83,8 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) { isRefreshing, width, setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, @@ -319,8 +321,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 a0fafa4a45..2ed3d74ff0 100644 --- a/superset-frontend/src/filters/components/Select/transformProps.ts +++ b/superset-frontend/src/filters/components/Select/transformProps.ts @@ -39,6 +39,8 @@ export default function transformProps( const newFormData = { ...DEFAULT_FORM_DATA, ...formData }; const { setDataMask = noOp, + setHoveredFilter = noOp, + unsetHoveredFilter = noOp, setFocusedFilter = noOp, unsetFocusedFilter = noOp, setFilterActive = noOp, @@ -61,6 +63,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 0d4185b759..d112d2daf5 100644 --- a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx @@ -66,6 +66,8 @@ const ControlContainer = styled.div<{ export default function TimeFilterPlugin(props: PluginFilterTimeProps) { const { setDataMask, + setHoveredFilter, + unsetHoveredFilter, setFocusedFilter, unsetFocusedFilter, setFilterActive, @@ -104,8 +106,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; }