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>
This commit is contained in:
Geido 2022-12-02 15:03:01 +02:00 committed by GitHub
parent 7bc5f04368
commit df91664217
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 234 additions and 58 deletions

View File

@ -126,6 +126,7 @@ export type NativeFiltersState = {
filters: Filters;
filterSets: FilterSets;
focusedFilterId?: string;
hoveredFilterId?: string;
};
export type DashboardComponentMetadata = {

View File

@ -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

View File

@ -239,9 +239,8 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
const canEdit = useSelector<RootState, boolean>(
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
);
const directPathToChild = useSelector<RootState, string[]>(
state => state.dashboardState.directPathToChild,
);
const nativeFilters = useSelector((state: RootState) => state.nativeFilters);
const focusedFilterId = nativeFilters?.focusedFilterId;
const fullSizeChartId = useSelector<RootState, number | null>(
state => state.dashboardState.fullSizeChartId,
);
@ -369,7 +368,7 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
{showFilterBar &&
filterBarOrientation === FilterBarOrientation.HORIZONTAL && (
<FilterBar
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
orientation={FilterBarOrientation.HORIZONTAL}
/>
)}
@ -401,7 +400,7 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
</div>
),
[
directPathToChild,
focusedFilterId,
nativeFiltersEnabled,
filterBarOrientation,
editMode,
@ -437,7 +436,7 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
<StickyPanel ref={containerRef} width={filterBarWidth}>
<ErrorBoundary>
<FilterBar
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
orientation={FilterBarOrientation.VERTICAL}
verticalConfig={{
filtersOpen: dashboardFiltersOpen,

View File

@ -23,6 +23,7 @@ import cx from 'classnames';
import { DataMaskStateWithId, Filters } from '@superset-ui/core';
import Icons from 'src/components/Icons';
import { usePrevious } from 'src/hooks/usePrevious';
import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters';
import DetailsPanelPopover from './DetailsPanel';
import { Pill } from './Styles';
import {
@ -31,7 +32,6 @@ import {
selectIndicatorsForChart,
selectNativeIndicatorsForChart,
} from './selectors';
import { setDirectPathToChild } from '../../actions/dashboardState';
import {
ChartsState,
DashboardInfo,
@ -87,7 +87,7 @@ export const FiltersBadge = ({ chartId }: FiltersBadgeProps) => {
const onHighlightFilterSource = useCallback(
(path: string[]) => {
dispatch(setDirectPathToChild(path));
dispatch(setFocusedNativeFilter(path[0]));
},
[dispatch],
);

View File

@ -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 (
<DragDroppable

View File

@ -217,7 +217,7 @@ const FilterControl = ({
filter,
icon,
onFilterSelectionChange,
directPathToChild,
focusedFilterId,
inView,
showOverflow,
parentRef,
@ -298,7 +298,7 @@ const FilterControl = ({
dataMaskSelected={dataMaskSelected}
filter={filter}
showOverflow={showOverflow}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
onFilterSelectionChange={onFilterSelectionChange}
inView={inView}
parentRef={parentRef}

View File

@ -16,7 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { FC, useCallback, useMemo, useState } from 'react';
import React, {
FC,
useEffect,
useCallback,
useMemo,
useRef,
useState,
} from 'react';
import {
DataMask,
DataMaskStateWithId,
@ -40,20 +47,22 @@ import {
useSelectFiltersInScope,
} from 'src/dashboard/components/nativeFilters/state';
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
import DropdownContainer from 'src/components/DropdownContainer';
import DropdownContainer, {
Ref as DropdownContainerRef,
} from 'src/components/DropdownContainer';
import Icons from 'src/components/Icons';
import { FiltersOutOfScopeCollapsible } from '../FiltersOutOfScopeCollapsible';
import { useFilterControlFactory } from '../useFilterControlFactory';
import { FiltersDropdownContent } from '../FiltersDropdownContent';
type FilterControlsProps = {
directPathToChild?: string[];
focusedFilterId?: string;
dataMaskSelected: DataMaskStateWithId;
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
};
const FilterControls: FC<FilterControlsProps> = ({
directPathToChild,
focusedFilterId,
dataMaskSelected,
onFilterSelectionChange,
}) => {
@ -65,10 +74,11 @@ const FilterControls: FC<FilterControlsProps> = ({
);
const [overflowedIds, setOverflowedIds] = useState<string[]>([]);
const popoverRef = useRef<DropdownContainerRef>(null);
const { filterControlFactory, filtersWithValues } = useFilterControlFactory(
dataMaskSelected,
directPathToChild,
focusedFilterId,
onFilterSelectionChange,
);
const portalNodes = useMemo(() => {
@ -183,6 +193,7 @@ const FilterControls: FC<FilterControlsProps> = ({
)
: undefined
}
ref={popoverRef}
onOverflowingStateChange={({ overflowed: nextOverflowedIds }) => {
if (
nextOverflowedIds.length !== overflowedIds.length ||
@ -211,6 +222,12 @@ const FilterControls: FC<FilterControlsProps> = ({
);
}, [filtersOutOfScope, filtersWithValues, overflowedFiltersInScope]);
useEffect(() => {
if (focusedFilterId && overflowedIds.includes(focusedFilterId)) {
popoverRef?.current?.open();
}
}, [focusedFilterId, popoverRef, overflowedIds]);
return (
<>
{portalNodes

View File

@ -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<FilterControlProps> = ({
dataMaskSelected,
filter,
directPathToChild,
focusedFilterId,
onFilterSelectionChange,
inView = true,
showOverflow,
@ -211,10 +212,12 @@ const FilterValue: React.FC<FilterControlProps> = ({
]);
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<FilterControlProps> = ({
[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(

View File

@ -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;

View File

@ -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<any>, id?: string) => {
if (id) {
dispatch(setHoveredNativeFilter(id));
} else {
dispatch(unsetHoveredNativeFilter());
}
},
FAST_DEBOUNCE,
);
export const dispatchFocusAction = debounce(
(dispatch: Dispatch<any>, id?: string) => {
@ -31,5 +45,5 @@ export const dispatchFocusAction = debounce(
dispatch(unsetFocusedNativeFilter());
}
},
300,
FAST_DEBOUNCE,
);

View File

@ -93,7 +93,7 @@ const HorizontalFilterBar: React.FC<HorizontalBarProps> = ({
dataMaskSelected,
filterValues,
isInitialized,
directPathToChild,
focusedFilterId,
onSelectionChange,
}) => {
const hasFilters = filterValues.length > 0;
@ -124,7 +124,7 @@ const HorizontalFilterBar: React.FC<HorizontalBarProps> = ({
{hasFilters && (
<FilterControls
dataMaskSelected={dataMaskSelected}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
onFilterSelectionChange={onSelectionChange}
/>
)}

View File

@ -141,7 +141,7 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
actions,
canEdit,
dataMaskSelected,
directPathToChild,
focusedFilterId,
filtersOpen,
filterValues,
height,
@ -258,7 +258,7 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
<FilterControlsWrapper>
<FilterControls
dataMaskSelected={dataMaskSelected}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
onFilterSelectionChange={onSelectionChange}
/>
</FilterControlsWrapper>
@ -300,7 +300,7 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
<FilterControlsWrapper>
<FilterControls
dataMaskSelected={dataMaskSelected}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
onFilterSelectionChange={onSelectionChange}
/>
</FilterControlsWrapper>

View File

@ -111,7 +111,7 @@ const publishDataMask = debounce(
export const FilterBarScrollContext = createContext(false);
const FilterBar: React.FC<FiltersBarProps> = ({
directPathToChild,
focusedFilterId,
orientation = FilterBarOrientation.VERTICAL,
verticalConfig,
}) => {
@ -254,7 +254,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
canEdit={canEdit}
dashboardId={dashboardId}
dataMaskSelected={dataMaskSelected}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
filterValues={filterValues}
isInitialized={isInitialized}
onSelectionChange={handleFilterSelectionChange}
@ -264,7 +264,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
actions={actions}
canEdit={canEdit}
dataMaskSelected={dataMaskSelected}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
filtersOpen={verticalConfig.filtersOpen}
filterValues={filterValues}
isInitialized={isInitialized}

View File

@ -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<CommonFiltersBarProps, 'directPathToChild'> {
extends Pick<CommonFiltersBarProps, 'focusedFilterId'> {
orientation: FilterBarOrientation;
verticalConfig?: VerticalBarConfig;
}

View File

@ -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 = (
<FilterControl
dataMaskSelected={dataMaskSelected}
filter={filter}
directPathToChild={directPathToChild}
focusedFilterId={focusedFilterId}
onFilterSelectionChange={onFilterSelectionChange}
inView={false}
orientation={filterBarOrientation}
@ -79,7 +79,7 @@ export const useFilterControlFactory = (
[
filtersWithValues,
dataMaskSelected,
directPathToChild,
focusedFilterId,
onFilterSelectionChange,
],
);

View File

@ -19,9 +19,9 @@
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 { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters';
import {
DependencyItem,
Row,
@ -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 (
<span>

View File

@ -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',
});
});
});

View File

@ -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;

View File

@ -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({

View File

@ -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,
)
) {

View File

@ -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}

View File

@ -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,

View File

@ -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)}
>

View File

@ -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,

View File

@ -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}

View File

@ -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,

View File

@ -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}
>
<DateFilterControl
value={filterState.value || NO_TIME_RANGE}

View File

@ -34,6 +34,8 @@ export default function transformProps(chartProps: ChartProps) {
} = chartProps;
const {
setDataMask = noOp,
setHoveredFilter = noOp,
unsetHoveredFilter = noOp,
setFocusedFilter = noOp,
unsetFocusedFilter = noOp,
setFilterActive = noOp,
@ -50,6 +52,8 @@ export default function transformProps(chartProps: ChartProps) {
height,
behaviors,
setDataMask,
setHoveredFilter,
unsetHoveredFilter,
setFocusedFilter,
unsetFocusedFilter,
setFilterActive,

View File

@ -38,6 +38,8 @@ export default function PluginFilterTimeColumn(
height,
width,
setDataMask,
setHoveredFilter,
unsetHoveredFilter,
setFocusedFilter,
unsetFocusedFilter,
setFilterActive,
@ -114,8 +116,10 @@ export default function PluginFilterTimeColumn(
placeholder={placeholderText}
// @ts-ignore
onChange={handleChange}
onMouseEnter={setFocusedFilter}
onMouseLeave={unsetFocusedFilter}
onBlur={unsetFocusedFilter}
onFocus={setFocusedFilter}
onMouseEnter={setHoveredFilter}
onMouseLeave={unsetHoveredFilter}
ref={inputRef}
options={options}
onDropdownVisibleChange={setFilterActive}

View File

@ -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,

View File

@ -38,6 +38,8 @@ export default function PluginFilterTimegrain(
height,
width,
setDataMask,
setHoveredFilter,
unsetHoveredFilter,
setFocusedFilter,
unsetFocusedFilter,
setFilterActive,
@ -124,8 +126,10 @@ export default function PluginFilterTimegrain(
placeholder={placeholderText}
// @ts-ignore
onChange={handleChange}
onMouseEnter={setFocusedFilter}
onMouseLeave={unsetFocusedFilter}
onBlur={unsetFocusedFilter}
onFocus={setFocusedFilter}
onMouseEnter={setHoveredFilter}
onMouseLeave={unsetHoveredFilter}
ref={inputRef}
options={options}
onDropdownVisibleChange={setFilterActive}

View File

@ -25,6 +25,8 @@ export default function transformProps(chartProps: ChartProps) {
chartProps;
const {
setDataMask = noOp,
setHoveredFilter = noOp,
unsetHoveredFilter = noOp,
setFocusedFilter = noOp,
unsetFocusedFilter = noOp,
setFilterActive = noOp,
@ -39,6 +41,8 @@ export default function transformProps(chartProps: ChartProps) {
data,
formData: { ...DEFAULT_FORM_DATA, ...formData },
setDataMask,
setHoveredFilter,
unsetHoveredFilter,
setFocusedFilter,
unsetFocusedFilter,
setFilterActive,

View File

@ -30,5 +30,7 @@ export interface PluginFilterHooks {
setDataMask: SetDataMaskHook;
setFocusedFilter: () => void;
unsetFocusedFilter: () => void;
setHoveredFilter: () => void;
unsetHoveredFilter: () => void;
setFilterActive: (isActive: boolean) => void;
}