diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx index f962a72e478e..e94bca37751d 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx @@ -21,6 +21,7 @@ import { SearchOutlined } from '@ant-design/icons'; import React, { FC } from 'react'; import { getFilterValueForDisplay } from 'src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils'; import { + FilterIndicatorText, FilterValue, Item, ItemIcon, @@ -31,24 +32,29 @@ import { Indicator } from 'src/dashboard/components/FiltersBadge/selectors'; export interface IndicatorProps { indicator: Indicator; onClick?: (path: string[]) => void; + text?: string; } const FilterIndicator: FC = ({ indicator: { column, name, value, path = [] }, onClick = () => {}, + text, }) => { const resultValue = getFilterValueForDisplay(value); return ( - onClick([...path, `LABEL-${column}`])}> - - <ItemIcon> - <SearchOutlined /> - </ItemIcon> - {name} - {resultValue ? ': ' : ''} - - {resultValue} - + <> + onClick([...path, `LABEL-${column}`])}> + + <ItemIcon> + <SearchOutlined /> + </ItemIcon> + {name} + {resultValue ? ': ' : ''} + + {resultValue} + + {text && {text}} + ); }; diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/Styles.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/Styles.tsx index 74ffd1967789..928996d451fd 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/Styles.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/Styles.tsx @@ -153,3 +153,13 @@ export const FilterValue = styled.div` overflow: auto; 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}; + `} +`; diff --git a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx index 2e0e234b6113..87425ec2026a 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx @@ -19,13 +19,14 @@ import React, { FC } from 'react'; import { styled, t } from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import EditableTitle from 'src/components/EditableTitle'; import SliceHeaderControls from 'src/dashboard/components/SliceHeaderControls'; import FiltersBadge from 'src/dashboard/components/FiltersBadge'; import Icon from 'src/components/Icon'; import { RootState } from 'src/dashboard/types'; import FilterIndicator from 'src/dashboard/components/FiltersBadge/FilterIndicator'; +import { clearDataMask } from 'src/dataMask/actions'; type SliceHeaderProps = { innerRef?: string; @@ -70,9 +71,12 @@ const annotationsError = t('One ore more annotation layers failed loading.'); const CrossFilterIcon = styled(Icon)` fill: ${({ theme }) => theme.colors.grayscale.light5}; + cursor: pointer; & circle { fill: ${({ theme }) => theme.colors.primary.base}; } + height: 22px; + width: 22px; `; const SliceHeader: FC = ({ @@ -105,6 +109,7 @@ const SliceHeader: FC = ({ chartStatus, formData, }) => { + const dispatch = useDispatch(); // TODO: change to indicator field after it will be implemented const crossFilterValue = useSelector( state => state.dataMask[slice?.slice_id]?.filterState?.value, @@ -164,10 +169,14 @@ const SliceHeader: FC = ({ value: crossFilterValue, name: t('Emitted values'), }} + text={t('Click to clear emitted filters')} /> } > - + dispatch(clearDataMask(slice?.slice_id))} + /> )} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx index cc10572060c9..e1d273ed1073 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx @@ -21,9 +21,8 @@ import { styled, t, useTheme } from '@superset-ui/core'; import React, { FC } from 'react'; import Icons from 'src/components/Icons'; 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 { getInitialDataMask } from 'src/dataMask/reducer'; import { DataMaskState, DataMaskStateWithId } from 'src/dataMask/types'; import FilterConfigurationLink from 'src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink'; import { useFilters } from 'src/dashboard/components/nativeFilters/FilterBar/state'; @@ -93,16 +92,7 @@ const Header: FC = ({ const filterIds = Object.keys(dataMaskSelected); filterIds.forEach(filterId => { if (dataMaskSelected[filterId]) { - dispatch( - updateDataMask( - filterId, - getInitialDataMask(filterId, { - filterState: { - value: null, - }, - }), - ), - ); + dispatch(clearDataMask(filterId)); } }); }; diff --git a/superset-frontend/src/dataMask/actions.ts b/superset-frontend/src/dataMask/actions.ts index 76a286c83348..1b7428ff7eaf 100644 --- a/superset-frontend/src/dataMask/actions.ts +++ b/superset-frontend/src/dataMask/actions.ts @@ -20,11 +20,12 @@ import { DataMask } from '@superset-ui/core'; import { FilterConfiguration } from '../dashboard/components/nativeFilters/types'; import { FeatureFlag, isFeatureEnabled } from '../featureFlags'; import { Filters } from '../dashboard/reducers/types'; +import { getInitialDataMask } from './reducer'; export const UPDATE_DATA_MASK = 'UPDATE_DATA_MASK'; export interface UpdateDataMask { type: typeof UPDATE_DATA_MASK; - filterId: string; + filterId: string | number; dataMask: DataMask; } @@ -55,7 +56,7 @@ export function setDataMaskForFilterConfigComplete( }; } export function updateDataMask( - filterId: string, + filterId: string | number, dataMask: DataMask, ): UpdateDataMask { // 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 = | UpdateDataMask | SetDataMaskForFilterConfigFail diff --git a/superset-frontend/src/dataMask/reducer.ts b/superset-frontend/src/dataMask/reducer.ts index 81c55a3498d7..4a4e240d40d8 100644 --- a/superset-frontend/src/dataMask/reducer.ts +++ b/superset-frontend/src/dataMask/reducer.ts @@ -37,9 +37,12 @@ import { import { areObjectsEqual } from '../reduxUtils'; import { Filters } from '../dashboard/reducers/types'; -export function getInitialDataMask(id?: string, moreProps?: DataMask): DataMask; export function getInitialDataMask( - id: string, + id?: string | number, + moreProps?: DataMask, +): DataMask; +export function getInitialDataMask( + id: string | number, moreProps: DataMask = {}, ): DataMaskWithId { let otherProps = {};