From c1b9d8844d3f11c4510fcc3534763248f397ffb1 Mon Sep 17 00:00:00 2001 From: geido Date: Wed, 30 Nov 2022 17:11:00 +0200 Subject: [PATCH 1/9] Open dropdown programmatically --- .../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 | 32 ++++++++++++--- .../FilterBar/FilterControls/types.ts | 2 +- .../FilterBar/FilterControls/utils.ts | 13 +++++++ .../nativeFilters/FilterBar/Horizontal.tsx | 4 +- .../nativeFilters/FilterBar/Vertical.tsx | 6 +-- .../nativeFilters/FilterBar/index.tsx | 6 +-- .../nativeFilters/FilterBar/types.ts | 4 +- .../FilterBar/useFilterControlFactory.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 + 31 files changed, 226 insertions(+), 52 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 90c1e5856ec31..9f46ecfa47549 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 6a3c516afd72d..079fce46a7a1b 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, ); @@ -366,7 +365,7 @@ const DashboardBuilder: FC = () => { {showFilterBar && filterBarOrientation === FilterBarOrientation.HORIZONTAL && ( )} @@ -398,7 +397,7 @@ const DashboardBuilder: FC = () => { ), [ - directPathToChild, + focusedFilterId, nativeFiltersEnabled, filterBarOrientation, editMode, @@ -434,7 +433,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..3b0732ac23b3b 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 highlighterFilterId = + nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId; + if (highlighterFilterId) { + tabsToHighlight = nativeFilters.filters[highlighterFilterId]?.tabsInScope; } return ( void; }; const FilterControls: FC = ({ - directPathToChild, + focusedFilterId, dataMaskSelected, onFilterSelectionChange, }) => { @@ -60,10 +69,11 @@ const FilterControls: FC = ({ ); const [overflowedIds, setOverflowedIds] = useState([]); + const popoverRef = useRef(null); const { filterControlFactory, filtersWithValues } = useFilterControlFactory( dataMaskSelected, - directPathToChild, + focusedFilterId, onFilterSelectionChange, ); const portalNodes = useMemo(() => { @@ -169,6 +179,7 @@ const FilterControls: FC = ({ ) : undefined } + ref={popoverRef} onOverflowingStateChange={({ overflowed: nextOverflowedIds }) => { if ( nextOverflowedIds.length !== overflowedIds.length || @@ -197,6 +208,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..0c9641f516d8f 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,7 @@ 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 { dispatchHoverAction, dispatchFocusAction } from './utils'; import { FilterControlProps } from './types'; import { getFormData } from '../../utils'; import { useFilterDependencies } from './state'; @@ -78,7 +78,7 @@ const useShouldFilterRefresh = () => { const FilterValue: React.FC = ({ dataMaskSelected, filter, - directPathToChild, + focusedFilterId, onFilterSelectionChange, inView = true, showOverflow, @@ -211,10 +211,12 @@ const FilterValue: React.FC = ({ ]); useEffect(() => { - if (directPathToChild?.[0] === filter.id) { - inputRef?.current?.focus(); + if (focusedFilterId && focusedFilterId === filter.id) { + setTimeout(() => { + inputRef?.current?.focus(); + }, 100); } - }, [inputRef, directPathToChild, filter.id]); + }, [inputRef, focusedFilterId, filter.id]); const setDataMask = useCallback( (dataMask: DataMask) => onFilterSelectionChange(filter, dataMask), @@ -230,14 +232,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..546d65a344a6d 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts @@ -21,8 +21,21 @@ import { Dispatch } from 'react'; import { setFocusedNativeFilter, unsetFocusedNativeFilter, + setHoveredNativeFilter, + unsetHoveredNativeFilter, } from 'src/dashboard/actions/nativeFilters'; +export const dispatchHoverAction = debounce( + (dispatch: Dispatch, id?: string) => { + if (id) { + dispatch(setHoveredNativeFilter(id)); + } else { + dispatch(unsetHoveredNativeFilter()); + } + }, + 300, +); + export const dispatchFocusAction = debounce( (dispatch: Dispatch, id?: string) => { if (id) { 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 = ( { 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..c64bc508ce2e6 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 highlighterFilterId = + nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId; + if (!(focusedFilterScope || highlighterFilterId)) { return {}; } @@ -67,9 +68,9 @@ const useFilterFocusHighlightStyles = (chartId: number) => { pointerEvents: 'auto', }; - if (focusedNativeFilterId) { + if (highlighterFilterId) { if ( - nativeFilters.filters[focusedNativeFilterId]?.chartsInScope?.includes( + nativeFilters.filters[highlighterFilterId]?.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; } From cd2698864b6c12a6388652aaaa656d81cf4b243e Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Thu, 1 Dec 2022 12:44:47 +0200 Subject: [PATCH 2/9] Update superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com> --- .../src/dashboard/components/gridComponents/Tabs.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx index 3b0732ac23b3b..2588ce59100e8 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx @@ -340,10 +340,10 @@ export class Tabs extends React.PureComponent { const { tabIndex: selectedTabIndex, activeKey } = this.state; let tabsToHighlight; - const highlighterFilterId = + const highlightedFilterId = nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId; - if (highlighterFilterId) { - tabsToHighlight = nativeFilters.filters[highlighterFilterId]?.tabsInScope; + if (highlightedFilterId) { + tabsToHighlight = nativeFilters.filters[highlightedFilterId]?.tabsInScope; } return ( Date: Thu, 1 Dec 2022 12:44:58 +0200 Subject: [PATCH 3/9] Update superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com> --- .../src/dashboard/util/useFilterFocusHighlightStyles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts index c64bc508ce2e6..69e2241bc4250 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts @@ -68,7 +68,7 @@ const useFilterFocusHighlightStyles = (chartId: number) => { pointerEvents: 'auto', }; - if (highlighterFilterId) { + if (highlightedFilterId) { if ( nativeFilters.filters[highlighterFilterId]?.chartsInScope?.includes( chartId, From 2ec5783100ac8364b00c13bacbdc75c8c01cc303 Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Thu, 1 Dec 2022 12:45:15 +0200 Subject: [PATCH 4/9] Update superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com> --- .../src/dashboard/util/useFilterFocusHighlightStyles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts index 69e2241bc4250..a129629e950bb 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts @@ -49,9 +49,9 @@ const useFilterFocusHighlightStyles = (chartId: number) => { dashboardFilters, ); - const highlighterFilterId = + const highlightedFilterId = nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId; - if (!(focusedFilterScope || highlighterFilterId)) { + if (!(focusedFilterScope || highlightedFilterId)) { return {}; } From eb0a209e55e4c0f9e5f5c0396ee95dcb960f114b Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Thu, 1 Dec 2022 12:45:24 +0200 Subject: [PATCH 5/9] Update superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com> --- .../src/dashboard/util/useFilterFocusHighlightStyles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts index a129629e950bb..8be43490ad3aa 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts @@ -70,7 +70,7 @@ const useFilterFocusHighlightStyles = (chartId: number) => { if (highlightedFilterId) { if ( - nativeFilters.filters[highlighterFilterId]?.chartsInScope?.includes( + nativeFilters.filters[highlightedFilterId]?.chartsInScope?.includes( chartId, ) ) { From 5a11835dca7a92599434e61a3a6ad1cd29f04ab0 Mon Sep 17 00:00:00 2001 From: geido Date: Thu, 1 Dec 2022 12:59:18 +0200 Subject: [PATCH 6/9] Use FAST_DEBOUNCE --- .../nativeFilters/FilterBar/FilterControls/FilterValue.tsx | 3 ++- .../nativeFilters/FilterBar/FilterControls/utils.ts | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) 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 0c9641f516d8f..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,6 +44,7 @@ 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 { FAST_DEBOUNCE } from 'src/constants'; import { dispatchHoverAction, dispatchFocusAction } from './utils'; import { FilterControlProps } from './types'; import { getFormData } from '../../utils'; @@ -214,7 +215,7 @@ const FilterValue: React.FC = ({ if (focusedFilterId && focusedFilterId === filter.id) { setTimeout(() => { inputRef?.current?.focus(); - }, 100); + }, FAST_DEBOUNCE); } }, [inputRef, focusedFilterId, filter.id]); 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 546d65a344a6d..5e0e159d1189d 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts @@ -24,6 +24,7 @@ import { setHoveredNativeFilter, unsetHoveredNativeFilter, } from 'src/dashboard/actions/nativeFilters'; +import { FAST_DEBOUNCE } from 'src/constants'; export const dispatchHoverAction = debounce( (dispatch: Dispatch, id?: string) => { @@ -33,7 +34,7 @@ export const dispatchHoverAction = debounce( dispatch(unsetHoveredNativeFilter()); } }, - 300, + FAST_DEBOUNCE, ); export const dispatchFocusAction = debounce( @@ -44,5 +45,5 @@ export const dispatchFocusAction = debounce( dispatch(unsetFocusedNativeFilter()); } }, - 300, + FAST_DEBOUNCE, ); From 5d509f3fec84927a3ce1499b27c4e59297bd4425 Mon Sep 17 00:00:00 2001 From: geido Date: Fri, 2 Dec 2022 11:03:12 +0200 Subject: [PATCH 7/9] Fix dependent filters --- .../components/nativeFilters/FilterCard/DependenciesRow.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx index 704357c134868..2718a5534bb11 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx @@ -19,7 +19,6 @@ import React, { useCallback, useMemo, useRef } from 'react'; import { useDispatch } from 'react-redux'; import { css, t, useTheme } from '@superset-ui/core'; -import { setDirectPathToChild } from 'src/dashboard/actions/dashboardState'; import Icons from 'src/components/Icons'; import { useTruncation } from 'src/hooks/useTruncation'; import { @@ -33,6 +32,7 @@ import { import { useFilterDependencies } from './useFilterDependencies'; import { DependencyValueProps, FilterCardRowProps } from './types'; import { TooltipWithTruncation } from './TooltipWithTruncation'; +import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters'; const DependencyValue = ({ dependency, @@ -40,7 +40,7 @@ const DependencyValue = ({ }: DependencyValueProps) => { const dispatch = useDispatch(); const handleClick = useCallback(() => { - dispatch(setDirectPathToChild([dependency.id])); + dispatch(setFocusedNativeFilter(dependency.id)); }, [dependency.id, dispatch]); return ( From 85bf95353bf27a06705195a096f8d8c889ab60d2 Mon Sep 17 00:00:00 2001 From: geido Date: Fri, 2 Dec 2022 12:00:24 +0200 Subject: [PATCH 8/9] Lint --- .../components/nativeFilters/FilterCard/DependenciesRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx index 2718a5534bb11..ccffdf4b56678 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx @@ -21,6 +21,7 @@ import { useDispatch } from 'react-redux'; import { css, t, useTheme } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import { useTruncation } from 'src/hooks/useTruncation'; +import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters'; import { DependencyItem, Row, @@ -32,7 +33,6 @@ import { import { useFilterDependencies } from './useFilterDependencies'; import { DependencyValueProps, FilterCardRowProps } from './types'; import { TooltipWithTruncation } from './TooltipWithTruncation'; -import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters'; const DependencyValue = ({ dependency, From 0be39290d84bb179fe17d35128310b918947139b Mon Sep 17 00:00:00 2001 From: geido Date: Fri, 2 Dec 2022 13:51:11 +0200 Subject: [PATCH 9/9] Fix test --- .../components/nativeFilters/FilterCard/FilterCard.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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', }); }); });