mirror of
https://github.com/apache/superset.git
synced 2024-09-06 13:57:40 -04:00
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:
parent
7bc5f04368
commit
df91664217
@ -126,6 +126,7 @@ export type NativeFiltersState = {
|
|||||||
filters: Filters;
|
filters: Filters;
|
||||||
filterSets: FilterSets;
|
filterSets: FilterSets;
|
||||||
focusedFilterId?: string;
|
focusedFilterId?: string;
|
||||||
|
hoveredFilterId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DashboardComponentMetadata = {
|
export type DashboardComponentMetadata = {
|
||||||
|
@ -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 =
|
export type AnyFilterAction =
|
||||||
| SetFilterConfigBegin
|
| SetFilterConfigBegin
|
||||||
| SetFilterConfigComplete
|
| SetFilterConfigComplete
|
||||||
@ -383,6 +405,8 @@ export type AnyFilterAction =
|
|||||||
| SetBootstrapData
|
| SetBootstrapData
|
||||||
| SetFocusedNativeFilter
|
| SetFocusedNativeFilter
|
||||||
| UnsetFocusedNativeFilter
|
| UnsetFocusedNativeFilter
|
||||||
|
| SetHoveredNativeFilter
|
||||||
|
| UnsetHoveredNativeFilter
|
||||||
| CreateFilterSetBegin
|
| CreateFilterSetBegin
|
||||||
| CreateFilterSetComplete
|
| CreateFilterSetComplete
|
||||||
| CreateFilterSetFail
|
| CreateFilterSetFail
|
||||||
|
@ -239,9 +239,8 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
|
|||||||
const canEdit = useSelector<RootState, boolean>(
|
const canEdit = useSelector<RootState, boolean>(
|
||||||
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
|
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
|
||||||
);
|
);
|
||||||
const directPathToChild = useSelector<RootState, string[]>(
|
const nativeFilters = useSelector((state: RootState) => state.nativeFilters);
|
||||||
state => state.dashboardState.directPathToChild,
|
const focusedFilterId = nativeFilters?.focusedFilterId;
|
||||||
);
|
|
||||||
const fullSizeChartId = useSelector<RootState, number | null>(
|
const fullSizeChartId = useSelector<RootState, number | null>(
|
||||||
state => state.dashboardState.fullSizeChartId,
|
state => state.dashboardState.fullSizeChartId,
|
||||||
);
|
);
|
||||||
@ -369,7 +368,7 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
|
|||||||
{showFilterBar &&
|
{showFilterBar &&
|
||||||
filterBarOrientation === FilterBarOrientation.HORIZONTAL && (
|
filterBarOrientation === FilterBarOrientation.HORIZONTAL && (
|
||||||
<FilterBar
|
<FilterBar
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
orientation={FilterBarOrientation.HORIZONTAL}
|
orientation={FilterBarOrientation.HORIZONTAL}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -401,7 +400,7 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
nativeFiltersEnabled,
|
nativeFiltersEnabled,
|
||||||
filterBarOrientation,
|
filterBarOrientation,
|
||||||
editMode,
|
editMode,
|
||||||
@ -437,7 +436,7 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
|
|||||||
<StickyPanel ref={containerRef} width={filterBarWidth}>
|
<StickyPanel ref={containerRef} width={filterBarWidth}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<FilterBar
|
<FilterBar
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
orientation={FilterBarOrientation.VERTICAL}
|
orientation={FilterBarOrientation.VERTICAL}
|
||||||
verticalConfig={{
|
verticalConfig={{
|
||||||
filtersOpen: dashboardFiltersOpen,
|
filtersOpen: dashboardFiltersOpen,
|
||||||
|
@ -23,6 +23,7 @@ import cx from 'classnames';
|
|||||||
import { DataMaskStateWithId, Filters } from '@superset-ui/core';
|
import { DataMaskStateWithId, Filters } from '@superset-ui/core';
|
||||||
import Icons from 'src/components/Icons';
|
import Icons from 'src/components/Icons';
|
||||||
import { usePrevious } from 'src/hooks/usePrevious';
|
import { usePrevious } from 'src/hooks/usePrevious';
|
||||||
|
import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters';
|
||||||
import DetailsPanelPopover from './DetailsPanel';
|
import DetailsPanelPopover from './DetailsPanel';
|
||||||
import { Pill } from './Styles';
|
import { Pill } from './Styles';
|
||||||
import {
|
import {
|
||||||
@ -31,7 +32,6 @@ import {
|
|||||||
selectIndicatorsForChart,
|
selectIndicatorsForChart,
|
||||||
selectNativeIndicatorsForChart,
|
selectNativeIndicatorsForChart,
|
||||||
} from './selectors';
|
} from './selectors';
|
||||||
import { setDirectPathToChild } from '../../actions/dashboardState';
|
|
||||||
import {
|
import {
|
||||||
ChartsState,
|
ChartsState,
|
||||||
DashboardInfo,
|
DashboardInfo,
|
||||||
@ -87,7 +87,7 @@ export const FiltersBadge = ({ chartId }: FiltersBadgeProps) => {
|
|||||||
|
|
||||||
const onHighlightFilterSource = useCallback(
|
const onHighlightFilterSource = useCallback(
|
||||||
(path: string[]) => {
|
(path: string[]) => {
|
||||||
dispatch(setDirectPathToChild(path));
|
dispatch(setFocusedNativeFilter(path[0]));
|
||||||
},
|
},
|
||||||
[dispatch],
|
[dispatch],
|
||||||
);
|
);
|
||||||
|
@ -340,9 +340,10 @@ export class Tabs extends React.PureComponent {
|
|||||||
const { tabIndex: selectedTabIndex, activeKey } = this.state;
|
const { tabIndex: selectedTabIndex, activeKey } = this.state;
|
||||||
|
|
||||||
let tabsToHighlight;
|
let tabsToHighlight;
|
||||||
if (nativeFilters?.focusedFilterId) {
|
const highlightedFilterId =
|
||||||
tabsToHighlight =
|
nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId;
|
||||||
nativeFilters.filters[nativeFilters.focusedFilterId].tabsInScope;
|
if (highlightedFilterId) {
|
||||||
|
tabsToHighlight = nativeFilters.filters[highlightedFilterId]?.tabsInScope;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<DragDroppable
|
<DragDroppable
|
||||||
|
@ -217,7 +217,7 @@ const FilterControl = ({
|
|||||||
filter,
|
filter,
|
||||||
icon,
|
icon,
|
||||||
onFilterSelectionChange,
|
onFilterSelectionChange,
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
inView,
|
inView,
|
||||||
showOverflow,
|
showOverflow,
|
||||||
parentRef,
|
parentRef,
|
||||||
@ -298,7 +298,7 @@ const FilterControl = ({
|
|||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
showOverflow={showOverflow}
|
showOverflow={showOverflow}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
onFilterSelectionChange={onFilterSelectionChange}
|
onFilterSelectionChange={onFilterSelectionChange}
|
||||||
inView={inView}
|
inView={inView}
|
||||||
parentRef={parentRef}
|
parentRef={parentRef}
|
||||||
|
@ -16,7 +16,14 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React, { FC, useCallback, useMemo, useState } from 'react';
|
import React, {
|
||||||
|
FC,
|
||||||
|
useEffect,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import {
|
import {
|
||||||
DataMask,
|
DataMask,
|
||||||
DataMaskStateWithId,
|
DataMaskStateWithId,
|
||||||
@ -40,20 +47,22 @@ import {
|
|||||||
useSelectFiltersInScope,
|
useSelectFiltersInScope,
|
||||||
} from 'src/dashboard/components/nativeFilters/state';
|
} from 'src/dashboard/components/nativeFilters/state';
|
||||||
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
|
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 Icons from 'src/components/Icons';
|
||||||
import { FiltersOutOfScopeCollapsible } from '../FiltersOutOfScopeCollapsible';
|
import { FiltersOutOfScopeCollapsible } from '../FiltersOutOfScopeCollapsible';
|
||||||
import { useFilterControlFactory } from '../useFilterControlFactory';
|
import { useFilterControlFactory } from '../useFilterControlFactory';
|
||||||
import { FiltersDropdownContent } from '../FiltersDropdownContent';
|
import { FiltersDropdownContent } from '../FiltersDropdownContent';
|
||||||
|
|
||||||
type FilterControlsProps = {
|
type FilterControlsProps = {
|
||||||
directPathToChild?: string[];
|
focusedFilterId?: string;
|
||||||
dataMaskSelected: DataMaskStateWithId;
|
dataMaskSelected: DataMaskStateWithId;
|
||||||
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
|
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const FilterControls: FC<FilterControlsProps> = ({
|
const FilterControls: FC<FilterControlsProps> = ({
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
onFilterSelectionChange,
|
onFilterSelectionChange,
|
||||||
}) => {
|
}) => {
|
||||||
@ -65,10 +74,11 @@ const FilterControls: FC<FilterControlsProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [overflowedIds, setOverflowedIds] = useState<string[]>([]);
|
const [overflowedIds, setOverflowedIds] = useState<string[]>([]);
|
||||||
|
const popoverRef = useRef<DropdownContainerRef>(null);
|
||||||
|
|
||||||
const { filterControlFactory, filtersWithValues } = useFilterControlFactory(
|
const { filterControlFactory, filtersWithValues } = useFilterControlFactory(
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
onFilterSelectionChange,
|
onFilterSelectionChange,
|
||||||
);
|
);
|
||||||
const portalNodes = useMemo(() => {
|
const portalNodes = useMemo(() => {
|
||||||
@ -183,6 +193,7 @@ const FilterControls: FC<FilterControlsProps> = ({
|
|||||||
)
|
)
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
ref={popoverRef}
|
||||||
onOverflowingStateChange={({ overflowed: nextOverflowedIds }) => {
|
onOverflowingStateChange={({ overflowed: nextOverflowedIds }) => {
|
||||||
if (
|
if (
|
||||||
nextOverflowedIds.length !== overflowedIds.length ||
|
nextOverflowedIds.length !== overflowedIds.length ||
|
||||||
@ -211,6 +222,12 @@ const FilterControls: FC<FilterControlsProps> = ({
|
|||||||
);
|
);
|
||||||
}, [filtersOutOfScope, filtersWithValues, overflowedFiltersInScope]);
|
}, [filtersOutOfScope, filtersWithValues, overflowedFiltersInScope]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (focusedFilterId && overflowedIds.includes(focusedFilterId)) {
|
||||||
|
popoverRef?.current?.open();
|
||||||
|
}
|
||||||
|
}, [focusedFilterId, popoverRef, overflowedIds]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{portalNodes
|
{portalNodes
|
||||||
|
@ -44,7 +44,8 @@ import { waitForAsyncData } from 'src/middleware/asyncEvent';
|
|||||||
import { ClientErrorObject } from 'src/utils/getClientErrorObject';
|
import { ClientErrorObject } from 'src/utils/getClientErrorObject';
|
||||||
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
|
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
|
||||||
import { onFiltersRefreshSuccess } from 'src/dashboard/actions/dashboardState';
|
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 { FilterControlProps } from './types';
|
||||||
import { getFormData } from '../../utils';
|
import { getFormData } from '../../utils';
|
||||||
import { useFilterDependencies } from './state';
|
import { useFilterDependencies } from './state';
|
||||||
@ -78,7 +79,7 @@ const useShouldFilterRefresh = () => {
|
|||||||
const FilterValue: React.FC<FilterControlProps> = ({
|
const FilterValue: React.FC<FilterControlProps> = ({
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
filter,
|
filter,
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
onFilterSelectionChange,
|
onFilterSelectionChange,
|
||||||
inView = true,
|
inView = true,
|
||||||
showOverflow,
|
showOverflow,
|
||||||
@ -211,10 +212,12 @@ const FilterValue: React.FC<FilterControlProps> = ({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (directPathToChild?.[0] === filter.id) {
|
if (focusedFilterId && focusedFilterId === filter.id) {
|
||||||
|
setTimeout(() => {
|
||||||
inputRef?.current?.focus();
|
inputRef?.current?.focus();
|
||||||
|
}, FAST_DEBOUNCE);
|
||||||
}
|
}
|
||||||
}, [inputRef, directPathToChild, filter.id]);
|
}, [inputRef, focusedFilterId, filter.id]);
|
||||||
|
|
||||||
const setDataMask = useCallback(
|
const setDataMask = useCallback(
|
||||||
(dataMask: DataMask) => onFilterSelectionChange(filter, dataMask),
|
(dataMask: DataMask) => onFilterSelectionChange(filter, dataMask),
|
||||||
@ -230,14 +233,32 @@ const FilterValue: React.FC<FilterControlProps> = ({
|
|||||||
[dispatch],
|
[dispatch],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setHoveredFilter = useCallback(
|
||||||
|
() => dispatchHoverAction(dispatch, id),
|
||||||
|
[dispatch, id],
|
||||||
|
);
|
||||||
|
const unsetHoveredFilter = useCallback(
|
||||||
|
() => dispatchHoverAction(dispatch),
|
||||||
|
[dispatch],
|
||||||
|
);
|
||||||
|
|
||||||
const hooks = useMemo(
|
const hooks = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
}),
|
}),
|
||||||
[setDataMask, setFilterActive, setFocusedFilter, unsetFocusedFilter],
|
[
|
||||||
|
setDataMask,
|
||||||
|
setFilterActive,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
|
setFocusedFilter,
|
||||||
|
unsetFocusedFilter,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isMissingRequiredValue = checkIsMissingRequiredValue(
|
const isMissingRequiredValue = checkIsMissingRequiredValue(
|
||||||
|
@ -36,7 +36,7 @@ export interface FilterControlProps extends BaseFilterProps {
|
|||||||
dataMask?: DataMask;
|
dataMask?: DataMask;
|
||||||
};
|
};
|
||||||
icon?: React.ReactElement;
|
icon?: React.ReactElement;
|
||||||
directPathToChild?: string[];
|
focusedFilterId?: string;
|
||||||
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
|
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
|
||||||
inView?: boolean;
|
inView?: boolean;
|
||||||
showOverflow?: boolean;
|
showOverflow?: boolean;
|
||||||
|
@ -21,7 +21,21 @@ import { Dispatch } from 'react';
|
|||||||
import {
|
import {
|
||||||
setFocusedNativeFilter,
|
setFocusedNativeFilter,
|
||||||
unsetFocusedNativeFilter,
|
unsetFocusedNativeFilter,
|
||||||
|
setHoveredNativeFilter,
|
||||||
|
unsetHoveredNativeFilter,
|
||||||
} from 'src/dashboard/actions/nativeFilters';
|
} 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(
|
export const dispatchFocusAction = debounce(
|
||||||
(dispatch: Dispatch<any>, id?: string) => {
|
(dispatch: Dispatch<any>, id?: string) => {
|
||||||
@ -31,5 +45,5 @@ export const dispatchFocusAction = debounce(
|
|||||||
dispatch(unsetFocusedNativeFilter());
|
dispatch(unsetFocusedNativeFilter());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
300,
|
FAST_DEBOUNCE,
|
||||||
);
|
);
|
||||||
|
@ -93,7 +93,7 @@ const HorizontalFilterBar: React.FC<HorizontalBarProps> = ({
|
|||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
filterValues,
|
filterValues,
|
||||||
isInitialized,
|
isInitialized,
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
}) => {
|
}) => {
|
||||||
const hasFilters = filterValues.length > 0;
|
const hasFilters = filterValues.length > 0;
|
||||||
@ -124,7 +124,7 @@ const HorizontalFilterBar: React.FC<HorizontalBarProps> = ({
|
|||||||
{hasFilters && (
|
{hasFilters && (
|
||||||
<FilterControls
|
<FilterControls
|
||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
onFilterSelectionChange={onSelectionChange}
|
onFilterSelectionChange={onSelectionChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -141,7 +141,7 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
|
|||||||
actions,
|
actions,
|
||||||
canEdit,
|
canEdit,
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
filtersOpen,
|
filtersOpen,
|
||||||
filterValues,
|
filterValues,
|
||||||
height,
|
height,
|
||||||
@ -258,7 +258,7 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
|
|||||||
<FilterControlsWrapper>
|
<FilterControlsWrapper>
|
||||||
<FilterControls
|
<FilterControls
|
||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
onFilterSelectionChange={onSelectionChange}
|
onFilterSelectionChange={onSelectionChange}
|
||||||
/>
|
/>
|
||||||
</FilterControlsWrapper>
|
</FilterControlsWrapper>
|
||||||
@ -300,7 +300,7 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
|
|||||||
<FilterControlsWrapper>
|
<FilterControlsWrapper>
|
||||||
<FilterControls
|
<FilterControls
|
||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
onFilterSelectionChange={onSelectionChange}
|
onFilterSelectionChange={onSelectionChange}
|
||||||
/>
|
/>
|
||||||
</FilterControlsWrapper>
|
</FilterControlsWrapper>
|
||||||
|
@ -111,7 +111,7 @@ const publishDataMask = debounce(
|
|||||||
|
|
||||||
export const FilterBarScrollContext = createContext(false);
|
export const FilterBarScrollContext = createContext(false);
|
||||||
const FilterBar: React.FC<FiltersBarProps> = ({
|
const FilterBar: React.FC<FiltersBarProps> = ({
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
orientation = FilterBarOrientation.VERTICAL,
|
orientation = FilterBarOrientation.VERTICAL,
|
||||||
verticalConfig,
|
verticalConfig,
|
||||||
}) => {
|
}) => {
|
||||||
@ -254,7 +254,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
|
|||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
dashboardId={dashboardId}
|
dashboardId={dashboardId}
|
||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
filterValues={filterValues}
|
filterValues={filterValues}
|
||||||
isInitialized={isInitialized}
|
isInitialized={isInitialized}
|
||||||
onSelectionChange={handleFilterSelectionChange}
|
onSelectionChange={handleFilterSelectionChange}
|
||||||
@ -264,7 +264,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
|
|||||||
actions={actions}
|
actions={actions}
|
||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
filtersOpen={verticalConfig.filtersOpen}
|
filtersOpen={verticalConfig.filtersOpen}
|
||||||
filterValues={filterValues}
|
filterValues={filterValues}
|
||||||
isInitialized={isInitialized}
|
isInitialized={isInitialized}
|
||||||
|
@ -28,7 +28,7 @@ interface CommonFiltersBarProps {
|
|||||||
actions: React.ReactNode;
|
actions: React.ReactNode;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
dataMaskSelected: DataMaskStateWithId;
|
dataMaskSelected: DataMaskStateWithId;
|
||||||
directPathToChild?: string[];
|
focusedFilterId?: string;
|
||||||
filterValues: (Filter | Divider)[];
|
filterValues: (Filter | Divider)[];
|
||||||
isInitialized: boolean;
|
isInitialized: boolean;
|
||||||
onSelectionChange: (
|
onSelectionChange: (
|
||||||
@ -46,7 +46,7 @@ interface VerticalBarConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface FiltersBarProps
|
export interface FiltersBarProps
|
||||||
extends Pick<CommonFiltersBarProps, 'directPathToChild'> {
|
extends Pick<CommonFiltersBarProps, 'focusedFilterId'> {
|
||||||
orientation: FilterBarOrientation;
|
orientation: FilterBarOrientation;
|
||||||
verticalConfig?: VerticalBarConfig;
|
verticalConfig?: VerticalBarConfig;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import FilterDivider from './FilterControls/FilterDivider';
|
|||||||
|
|
||||||
export const useFilterControlFactory = (
|
export const useFilterControlFactory = (
|
||||||
dataMaskSelected: DataMaskStateWithId,
|
dataMaskSelected: DataMaskStateWithId,
|
||||||
directPathToChild: string[] | undefined,
|
focusedFilterId: string | undefined,
|
||||||
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void,
|
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void,
|
||||||
) => {
|
) => {
|
||||||
const filters = useFilters();
|
const filters = useFilters();
|
||||||
@ -68,7 +68,7 @@ export const useFilterControlFactory = (
|
|||||||
<FilterControl
|
<FilterControl
|
||||||
dataMaskSelected={dataMaskSelected}
|
dataMaskSelected={dataMaskSelected}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
directPathToChild={directPathToChild}
|
focusedFilterId={focusedFilterId}
|
||||||
onFilterSelectionChange={onFilterSelectionChange}
|
onFilterSelectionChange={onFilterSelectionChange}
|
||||||
inView={false}
|
inView={false}
|
||||||
orientation={filterBarOrientation}
|
orientation={filterBarOrientation}
|
||||||
@ -79,7 +79,7 @@ export const useFilterControlFactory = (
|
|||||||
[
|
[
|
||||||
filtersWithValues,
|
filtersWithValues,
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
directPathToChild,
|
focusedFilterId,
|
||||||
onFilterSelectionChange,
|
onFilterSelectionChange,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
import React, { useCallback, useMemo, useRef } from 'react';
|
import React, { useCallback, useMemo, useRef } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { css, t, useTheme } from '@superset-ui/core';
|
import { css, t, useTheme } from '@superset-ui/core';
|
||||||
import { setDirectPathToChild } from 'src/dashboard/actions/dashboardState';
|
|
||||||
import Icons from 'src/components/Icons';
|
import Icons from 'src/components/Icons';
|
||||||
import { useTruncation } from 'src/hooks/useTruncation';
|
import { useTruncation } from 'src/hooks/useTruncation';
|
||||||
|
import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters';
|
||||||
import {
|
import {
|
||||||
DependencyItem,
|
DependencyItem,
|
||||||
Row,
|
Row,
|
||||||
@ -40,7 +40,7 @@ const DependencyValue = ({
|
|||||||
}: DependencyValueProps) => {
|
}: DependencyValueProps) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
dispatch(setDirectPathToChild([dependency.id]));
|
dispatch(setFocusedNativeFilter(dependency.id));
|
||||||
}, [dependency.id, dispatch]);
|
}, [dependency.id, dispatch]);
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
|
@ -23,7 +23,7 @@ import { Filter, NativeFilterType } from '@superset-ui/core';
|
|||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { render, screen } from 'spec/helpers/testing-library';
|
import { render, screen } from 'spec/helpers/testing-library';
|
||||||
import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants';
|
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';
|
import { FilterCardContent } from './FilterCardContent';
|
||||||
|
|
||||||
const baseInitialState = {
|
const baseInitialState = {
|
||||||
@ -298,8 +298,8 @@ describe('Filter Card', () => {
|
|||||||
|
|
||||||
userEvent.click(screen.getByText('Native filter 2'));
|
userEvent.click(screen.getByText('Native filter 2'));
|
||||||
expect(dummyDispatch).toHaveBeenCalledWith({
|
expect(dummyDispatch).toHaveBeenCalledWith({
|
||||||
type: SET_DIRECT_PATH,
|
type: SET_FOCUSED_NATIVE_FILTER,
|
||||||
path: ['NATIVE_FILTER-2'],
|
id: 'NATIVE_FILTER-2',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -23,6 +23,8 @@ import {
|
|||||||
SET_FILTER_SETS_COMPLETE,
|
SET_FILTER_SETS_COMPLETE,
|
||||||
SET_FOCUSED_NATIVE_FILTER,
|
SET_FOCUSED_NATIVE_FILTER,
|
||||||
UNSET_FOCUSED_NATIVE_FILTER,
|
UNSET_FOCUSED_NATIVE_FILTER,
|
||||||
|
SET_HOVERED_NATIVE_FILTER,
|
||||||
|
UNSET_HOVERED_NATIVE_FILTER,
|
||||||
} from 'src/dashboard/actions/nativeFilters';
|
} from 'src/dashboard/actions/nativeFilters';
|
||||||
import {
|
import {
|
||||||
FilterSet,
|
FilterSet,
|
||||||
@ -102,6 +104,18 @@ export default function nativeFilterReducer(
|
|||||||
...state,
|
...state,
|
||||||
focusedFilterId: undefined,
|
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
|
// TODO handle SET_FILTER_CONFIG_FAIL action
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -79,6 +79,25 @@ describe('useFilterFocusHighlightStyles', () => {
|
|||||||
expect(parseFloat(styles.opacity)).toBe(0.3);
|
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 () => {
|
it('should return focused styles if chart is in scope of focused native filter', async () => {
|
||||||
const chartId = 18;
|
const chartId = 18;
|
||||||
const store = createMockStore({
|
const store = createMockStore({
|
||||||
@ -99,6 +118,26 @@ describe('useFilterFocusHighlightStyles', () => {
|
|||||||
expect(parseFloat(styles.opacity)).toBe(1);
|
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 () => {
|
it('should return unfocused styles if focusedFilterField is targeting a different chart', async () => {
|
||||||
const chartId = 18;
|
const chartId = 18;
|
||||||
const store = createMockStore({
|
const store = createMockStore({
|
||||||
|
@ -49,8 +49,9 @@ const useFilterFocusHighlightStyles = (chartId: number) => {
|
|||||||
dashboardFilters,
|
dashboardFilters,
|
||||||
);
|
);
|
||||||
|
|
||||||
const focusedNativeFilterId = nativeFilters.focusedFilterId;
|
const highlightedFilterId =
|
||||||
if (!(focusedFilterScope || focusedNativeFilterId)) {
|
nativeFilters?.focusedFilterId || nativeFilters?.hoveredFilterId;
|
||||||
|
if (!(focusedFilterScope || highlightedFilterId)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,9 +68,9 @@ const useFilterFocusHighlightStyles = (chartId: number) => {
|
|||||||
pointerEvents: 'auto',
|
pointerEvents: 'auto',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (focusedNativeFilterId) {
|
if (highlightedFilterId) {
|
||||||
if (
|
if (
|
||||||
nativeFilters.filters[focusedNativeFilterId]?.chartsInScope?.includes(
|
nativeFilters.filters[highlightedFilterId]?.chartsInScope?.includes(
|
||||||
chartId,
|
chartId,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -36,6 +36,8 @@ export default function PluginFilterGroupBy(props: PluginFilterGroupByProps) {
|
|||||||
height,
|
height,
|
||||||
width,
|
width,
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
@ -116,6 +118,8 @@ export default function PluginFilterGroupBy(props: PluginFilterGroupByProps) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onBlur={unsetFocusedFilter}
|
onBlur={unsetFocusedFilter}
|
||||||
onFocus={setFocusedFilter}
|
onFocus={setFocusedFilter}
|
||||||
|
onMouseEnter={setHoveredFilter}
|
||||||
|
onMouseLeave={unsetHoveredFilter}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
options={options}
|
options={options}
|
||||||
onDropdownVisibleChange={setFilterActive}
|
onDropdownVisibleChange={setFilterActive}
|
||||||
|
@ -33,6 +33,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
} = chartProps;
|
} = chartProps;
|
||||||
const {
|
const {
|
||||||
setDataMask = noOp,
|
setDataMask = noOp,
|
||||||
|
setHoveredFilter = noOp,
|
||||||
|
unsetHoveredFilter = noOp,
|
||||||
setFocusedFilter = noOp,
|
setFocusedFilter = noOp,
|
||||||
unsetFocusedFilter = noOp,
|
unsetFocusedFilter = noOp,
|
||||||
setFilterActive = noOp,
|
setFilterActive = noOp,
|
||||||
@ -48,6 +50,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
data,
|
data,
|
||||||
formData: { ...DEFAULT_FORM_DATA, ...formData },
|
formData: { ...DEFAULT_FORM_DATA, ...formData },
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
|
@ -171,6 +171,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) {
|
|||||||
setDataMask,
|
setDataMask,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
filterState,
|
filterState,
|
||||||
inputRef,
|
inputRef,
|
||||||
@ -312,8 +314,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) {
|
|||||||
isOverflowing={isOverflowingFilterBar}
|
isOverflowing={isOverflowingFilterBar}
|
||||||
onFocus={setFocusedFilter}
|
onFocus={setFocusedFilter}
|
||||||
onBlur={unsetFocusedFilter}
|
onBlur={unsetFocusedFilter}
|
||||||
onMouseEnter={setFocusedFilter}
|
onMouseEnter={setHoveredFilter}
|
||||||
onMouseLeave={unsetFocusedFilter}
|
onMouseLeave={unsetHoveredFilter}
|
||||||
onMouseDown={() => setFilterActive(true)}
|
onMouseDown={() => setFilterActive(true)}
|
||||||
onMouseUp={() => setFilterActive(false)}
|
onMouseUp={() => setFilterActive(false)}
|
||||||
>
|
>
|
||||||
|
@ -35,6 +35,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
setDataMask = noOp,
|
setDataMask = noOp,
|
||||||
setFocusedFilter = noOp,
|
setFocusedFilter = noOp,
|
||||||
unsetFocusedFilter = noOp,
|
unsetFocusedFilter = noOp,
|
||||||
|
setHoveredFilter = noOp,
|
||||||
|
unsetHoveredFilter = noOp,
|
||||||
setFilterActive = noOp,
|
setFilterActive = noOp,
|
||||||
} = hooks;
|
} = hooks;
|
||||||
const { data } = queriesData[0];
|
const { data } = queriesData[0];
|
||||||
@ -47,6 +49,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
setDataMask,
|
setDataMask,
|
||||||
filterState,
|
filterState,
|
||||||
width,
|
width,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
|
@ -83,6 +83,8 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
|
|||||||
isRefreshing,
|
isRefreshing,
|
||||||
width,
|
width,
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
@ -319,8 +321,9 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
|
|||||||
onSearch={searchWrapper}
|
onSearch={searchWrapper}
|
||||||
onSelect={clearSuggestionSearch}
|
onSelect={clearSuggestionSearch}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
onMouseEnter={setFocusedFilter}
|
onFocus={setFocusedFilter}
|
||||||
onMouseLeave={unsetFocusedFilter}
|
onMouseEnter={setHoveredFilter}
|
||||||
|
onMouseLeave={unsetHoveredFilter}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
@ -39,6 +39,8 @@ export default function transformProps(
|
|||||||
const newFormData = { ...DEFAULT_FORM_DATA, ...formData };
|
const newFormData = { ...DEFAULT_FORM_DATA, ...formData };
|
||||||
const {
|
const {
|
||||||
setDataMask = noOp,
|
setDataMask = noOp,
|
||||||
|
setHoveredFilter = noOp,
|
||||||
|
unsetHoveredFilter = noOp,
|
||||||
setFocusedFilter = noOp,
|
setFocusedFilter = noOp,
|
||||||
unsetFocusedFilter = noOp,
|
unsetFocusedFilter = noOp,
|
||||||
setFilterActive = noOp,
|
setFilterActive = noOp,
|
||||||
@ -61,6 +63,8 @@ export default function transformProps(
|
|||||||
formData: newFormData,
|
formData: newFormData,
|
||||||
isRefreshing,
|
isRefreshing,
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
|
@ -66,6 +66,8 @@ const ControlContainer = styled.div<{
|
|||||||
export default function TimeFilterPlugin(props: PluginFilterTimeProps) {
|
export default function TimeFilterPlugin(props: PluginFilterTimeProps) {
|
||||||
const {
|
const {
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
@ -104,8 +106,8 @@ export default function TimeFilterPlugin(props: PluginFilterTimeProps) {
|
|||||||
validateStatus={filterState.validateStatus}
|
validateStatus={filterState.validateStatus}
|
||||||
onFocus={setFocusedFilter}
|
onFocus={setFocusedFilter}
|
||||||
onBlur={unsetFocusedFilter}
|
onBlur={unsetFocusedFilter}
|
||||||
onMouseEnter={setFocusedFilter}
|
onMouseEnter={setHoveredFilter}
|
||||||
onMouseLeave={unsetFocusedFilter}
|
onMouseLeave={unsetHoveredFilter}
|
||||||
>
|
>
|
||||||
<DateFilterControl
|
<DateFilterControl
|
||||||
value={filterState.value || NO_TIME_RANGE}
|
value={filterState.value || NO_TIME_RANGE}
|
||||||
|
@ -34,6 +34,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
} = chartProps;
|
} = chartProps;
|
||||||
const {
|
const {
|
||||||
setDataMask = noOp,
|
setDataMask = noOp,
|
||||||
|
setHoveredFilter = noOp,
|
||||||
|
unsetHoveredFilter = noOp,
|
||||||
setFocusedFilter = noOp,
|
setFocusedFilter = noOp,
|
||||||
unsetFocusedFilter = noOp,
|
unsetFocusedFilter = noOp,
|
||||||
setFilterActive = noOp,
|
setFilterActive = noOp,
|
||||||
@ -50,6 +52,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
height,
|
height,
|
||||||
behaviors,
|
behaviors,
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
|
@ -38,6 +38,8 @@ export default function PluginFilterTimeColumn(
|
|||||||
height,
|
height,
|
||||||
width,
|
width,
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
@ -114,8 +116,10 @@ export default function PluginFilterTimeColumn(
|
|||||||
placeholder={placeholderText}
|
placeholder={placeholderText}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onMouseEnter={setFocusedFilter}
|
onBlur={unsetFocusedFilter}
|
||||||
onMouseLeave={unsetFocusedFilter}
|
onFocus={setFocusedFilter}
|
||||||
|
onMouseEnter={setHoveredFilter}
|
||||||
|
onMouseLeave={unsetHoveredFilter}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
options={options}
|
options={options}
|
||||||
onDropdownVisibleChange={setFilterActive}
|
onDropdownVisibleChange={setFilterActive}
|
||||||
|
@ -33,6 +33,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
} = chartProps;
|
} = chartProps;
|
||||||
const {
|
const {
|
||||||
setDataMask = noOp,
|
setDataMask = noOp,
|
||||||
|
setHoveredFilter = noOp,
|
||||||
|
unsetHoveredFilter = noOp,
|
||||||
setFocusedFilter = noOp,
|
setFocusedFilter = noOp,
|
||||||
unsetFocusedFilter = noOp,
|
unsetFocusedFilter = noOp,
|
||||||
setFilterActive = noOp,
|
setFilterActive = noOp,
|
||||||
@ -48,6 +50,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
data,
|
data,
|
||||||
formData: { ...DEFAULT_FORM_DATA, ...formData },
|
formData: { ...DEFAULT_FORM_DATA, ...formData },
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
|
@ -38,6 +38,8 @@ export default function PluginFilterTimegrain(
|
|||||||
height,
|
height,
|
||||||
width,
|
width,
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
@ -124,8 +126,10 @@ export default function PluginFilterTimegrain(
|
|||||||
placeholder={placeholderText}
|
placeholder={placeholderText}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onMouseEnter={setFocusedFilter}
|
onBlur={unsetFocusedFilter}
|
||||||
onMouseLeave={unsetFocusedFilter}
|
onFocus={setFocusedFilter}
|
||||||
|
onMouseEnter={setHoveredFilter}
|
||||||
|
onMouseLeave={unsetHoveredFilter}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
options={options}
|
options={options}
|
||||||
onDropdownVisibleChange={setFilterActive}
|
onDropdownVisibleChange={setFilterActive}
|
||||||
|
@ -25,6 +25,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
chartProps;
|
chartProps;
|
||||||
const {
|
const {
|
||||||
setDataMask = noOp,
|
setDataMask = noOp,
|
||||||
|
setHoveredFilter = noOp,
|
||||||
|
unsetHoveredFilter = noOp,
|
||||||
setFocusedFilter = noOp,
|
setFocusedFilter = noOp,
|
||||||
unsetFocusedFilter = noOp,
|
unsetFocusedFilter = noOp,
|
||||||
setFilterActive = noOp,
|
setFilterActive = noOp,
|
||||||
@ -39,6 +41,8 @@ export default function transformProps(chartProps: ChartProps) {
|
|||||||
data,
|
data,
|
||||||
formData: { ...DEFAULT_FORM_DATA, ...formData },
|
formData: { ...DEFAULT_FORM_DATA, ...formData },
|
||||||
setDataMask,
|
setDataMask,
|
||||||
|
setHoveredFilter,
|
||||||
|
unsetHoveredFilter,
|
||||||
setFocusedFilter,
|
setFocusedFilter,
|
||||||
unsetFocusedFilter,
|
unsetFocusedFilter,
|
||||||
setFilterActive,
|
setFilterActive,
|
||||||
|
@ -30,5 +30,7 @@ export interface PluginFilterHooks {
|
|||||||
setDataMask: SetDataMaskHook;
|
setDataMask: SetDataMaskHook;
|
||||||
setFocusedFilter: () => void;
|
setFocusedFilter: () => void;
|
||||||
unsetFocusedFilter: () => void;
|
unsetFocusedFilter: () => void;
|
||||||
|
setHoveredFilter: () => void;
|
||||||
|
unsetHoveredFilter: () => void;
|
||||||
setFilterActive: (isActive: boolean) => void;
|
setFilterActive: (isActive: boolean) => void;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user