feat(cross-filters): add option to clear set cross filters (#15500)

* feat(cross-filters): add option to clear set cross filters

* lint

* fix indicator size, remove bolded text and rephrase text
This commit is contained in:
Ville Brofeldt 2021-07-02 17:04:05 +03:00 committed by GitHub
parent 99fe9c5657
commit ee2ee48661
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 28 deletions

View File

@ -21,6 +21,7 @@ import { SearchOutlined } from '@ant-design/icons';
import React, { FC } from 'react'; import React, { FC } from 'react';
import { getFilterValueForDisplay } from 'src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils'; import { getFilterValueForDisplay } from 'src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils';
import { import {
FilterIndicatorText,
FilterValue, FilterValue,
Item, Item,
ItemIcon, ItemIcon,
@ -31,24 +32,29 @@ import { Indicator } from 'src/dashboard/components/FiltersBadge/selectors';
export interface IndicatorProps { export interface IndicatorProps {
indicator: Indicator; indicator: Indicator;
onClick?: (path: string[]) => void; onClick?: (path: string[]) => void;
text?: string;
} }
const FilterIndicator: FC<IndicatorProps> = ({ const FilterIndicator: FC<IndicatorProps> = ({
indicator: { column, name, value, path = [] }, indicator: { column, name, value, path = [] },
onClick = () => {}, onClick = () => {},
text,
}) => { }) => {
const resultValue = getFilterValueForDisplay(value); const resultValue = getFilterValueForDisplay(value);
return ( return (
<Item onClick={() => onClick([...path, `LABEL-${column}`])}> <>
<Title bold> <Item onClick={() => onClick([...path, `LABEL-${column}`])}>
<ItemIcon> <Title bold>
<SearchOutlined /> <ItemIcon>
</ItemIcon> <SearchOutlined />
{name} </ItemIcon>
{resultValue ? ': ' : ''} {name}
</Title> {resultValue ? ': ' : ''}
<FilterValue>{resultValue}</FilterValue> </Title>
</Item> <FilterValue>{resultValue}</FilterValue>
</Item>
{text && <FilterIndicatorText>{text}</FilterIndicatorText>}
</>
); );
}; };

View File

@ -153,3 +153,13 @@ export const FilterValue = styled.div`
overflow: auto; overflow: auto;
color: ${({ theme }) => theme.colors.grayscale.light5}; color: ${({ theme }) => theme.colors.grayscale.light5};
`; `;
export const FilterIndicatorText = styled.div`
${({ theme }) => `
padding-top: ${theme.gridUnit * 3}px;
max-width: 100%;
flex-grow: 1;
overflow: auto;
color: ${theme.colors.grayscale.light5};
`}
`;

View File

@ -19,13 +19,14 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { styled, t } from '@superset-ui/core'; import { styled, t } from '@superset-ui/core';
import { Tooltip } from 'src/components/Tooltip'; import { Tooltip } from 'src/components/Tooltip';
import { useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import EditableTitle from 'src/components/EditableTitle'; import EditableTitle from 'src/components/EditableTitle';
import SliceHeaderControls from 'src/dashboard/components/SliceHeaderControls'; import SliceHeaderControls from 'src/dashboard/components/SliceHeaderControls';
import FiltersBadge from 'src/dashboard/components/FiltersBadge'; import FiltersBadge from 'src/dashboard/components/FiltersBadge';
import Icon from 'src/components/Icon'; import Icon from 'src/components/Icon';
import { RootState } from 'src/dashboard/types'; import { RootState } from 'src/dashboard/types';
import FilterIndicator from 'src/dashboard/components/FiltersBadge/FilterIndicator'; import FilterIndicator from 'src/dashboard/components/FiltersBadge/FilterIndicator';
import { clearDataMask } from 'src/dataMask/actions';
type SliceHeaderProps = { type SliceHeaderProps = {
innerRef?: string; innerRef?: string;
@ -70,9 +71,12 @@ const annotationsError = t('One ore more annotation layers failed loading.');
const CrossFilterIcon = styled(Icon)` const CrossFilterIcon = styled(Icon)`
fill: ${({ theme }) => theme.colors.grayscale.light5}; fill: ${({ theme }) => theme.colors.grayscale.light5};
cursor: pointer;
& circle { & circle {
fill: ${({ theme }) => theme.colors.primary.base}; fill: ${({ theme }) => theme.colors.primary.base};
} }
height: 22px;
width: 22px;
`; `;
const SliceHeader: FC<SliceHeaderProps> = ({ const SliceHeader: FC<SliceHeaderProps> = ({
@ -105,6 +109,7 @@ const SliceHeader: FC<SliceHeaderProps> = ({
chartStatus, chartStatus,
formData, formData,
}) => { }) => {
const dispatch = useDispatch();
// TODO: change to indicator field after it will be implemented // TODO: change to indicator field after it will be implemented
const crossFilterValue = useSelector<RootState, any>( const crossFilterValue = useSelector<RootState, any>(
state => state.dataMask[slice?.slice_id]?.filterState?.value, state => state.dataMask[slice?.slice_id]?.filterState?.value,
@ -164,10 +169,14 @@ const SliceHeader: FC<SliceHeaderProps> = ({
value: crossFilterValue, value: crossFilterValue,
name: t('Emitted values'), name: t('Emitted values'),
}} }}
text={t('Click to clear emitted filters')}
/> />
} }
> >
<CrossFilterIcon name="cross-filter-badge" /> <CrossFilterIcon
name="cross-filter-badge"
onClick={() => dispatch(clearDataMask(slice?.slice_id))}
/>
</Tooltip> </Tooltip>
)} )}
<FiltersBadge chartId={slice.slice_id} /> <FiltersBadge chartId={slice.slice_id} />

View File

@ -21,9 +21,8 @@ import { styled, t, useTheme } from '@superset-ui/core';
import React, { FC } from 'react'; import React, { FC } from 'react';
import Icons from 'src/components/Icons'; import Icons from 'src/components/Icons';
import Button from 'src/components/Button'; import Button from 'src/components/Button';
import { updateDataMask } from 'src/dataMask/actions'; import { clearDataMask } from 'src/dataMask/actions';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { getInitialDataMask } from 'src/dataMask/reducer';
import { DataMaskState, DataMaskStateWithId } from 'src/dataMask/types'; import { DataMaskState, DataMaskStateWithId } from 'src/dataMask/types';
import FilterConfigurationLink from 'src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink'; import FilterConfigurationLink from 'src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink';
import { useFilters } from 'src/dashboard/components/nativeFilters/FilterBar/state'; import { useFilters } from 'src/dashboard/components/nativeFilters/FilterBar/state';
@ -93,16 +92,7 @@ const Header: FC<HeaderProps> = ({
const filterIds = Object.keys(dataMaskSelected); const filterIds = Object.keys(dataMaskSelected);
filterIds.forEach(filterId => { filterIds.forEach(filterId => {
if (dataMaskSelected[filterId]) { if (dataMaskSelected[filterId]) {
dispatch( dispatch(clearDataMask(filterId));
updateDataMask(
filterId,
getInitialDataMask(filterId, {
filterState: {
value: null,
},
}),
),
);
} }
}); });
}; };

View File

@ -20,11 +20,12 @@ import { DataMask } from '@superset-ui/core';
import { FilterConfiguration } from '../dashboard/components/nativeFilters/types'; import { FilterConfiguration } from '../dashboard/components/nativeFilters/types';
import { FeatureFlag, isFeatureEnabled } from '../featureFlags'; import { FeatureFlag, isFeatureEnabled } from '../featureFlags';
import { Filters } from '../dashboard/reducers/types'; import { Filters } from '../dashboard/reducers/types';
import { getInitialDataMask } from './reducer';
export const UPDATE_DATA_MASK = 'UPDATE_DATA_MASK'; export const UPDATE_DATA_MASK = 'UPDATE_DATA_MASK';
export interface UpdateDataMask { export interface UpdateDataMask {
type: typeof UPDATE_DATA_MASK; type: typeof UPDATE_DATA_MASK;
filterId: string; filterId: string | number;
dataMask: DataMask; dataMask: DataMask;
} }
@ -55,7 +56,7 @@ export function setDataMaskForFilterConfigComplete(
}; };
} }
export function updateDataMask( export function updateDataMask(
filterId: string, filterId: string | number,
dataMask: DataMask, dataMask: DataMask,
): UpdateDataMask { ): UpdateDataMask {
// Only apply data mask if one of the relevant features is enabled // Only apply data mask if one of the relevant features is enabled
@ -69,6 +70,17 @@ export function updateDataMask(
}; };
} }
export function clearDataMask(filterId: string | number) {
return updateDataMask(
filterId,
getInitialDataMask(filterId, {
filterState: {
value: null,
},
}),
);
}
export type AnyDataMaskAction = export type AnyDataMaskAction =
| UpdateDataMask | UpdateDataMask
| SetDataMaskForFilterConfigFail | SetDataMaskForFilterConfigFail

View File

@ -37,9 +37,12 @@ import {
import { areObjectsEqual } from '../reduxUtils'; import { areObjectsEqual } from '../reduxUtils';
import { Filters } from '../dashboard/reducers/types'; import { Filters } from '../dashboard/reducers/types';
export function getInitialDataMask(id?: string, moreProps?: DataMask): DataMask;
export function getInitialDataMask( export function getInitialDataMask(
id: string, id?: string | number,
moreProps?: DataMask,
): DataMask;
export function getInitialDataMask(
id: string | number,
moreProps: DataMask = {}, moreProps: DataMask = {},
): DataMaskWithId { ): DataMaskWithId {
let otherProps = {}; let otherProps = {};