From 57e37ed4d5e4f9c2f161a80fcedba6fd5b3fc208 Mon Sep 17 00:00:00 2001 From: Agata Stawarz <47450693+agatapst@users.noreply.github.com> Date: Thu, 14 Jan 2021 19:57:41 +0100 Subject: [PATCH] fix: Displaying filter indicators (#12252) * Fix chart filter indicator to match native filter indicator * Refactor indicators deduplication --- .../components/FiltersBadge/selectors.ts | 46 +++++++++++++++++-- .../src/dashboard/containers/FiltersBadge.tsx | 28 ++++++++++- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts index 6aaa0d97a9..3eea0a4077 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts +++ b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts @@ -18,6 +18,10 @@ */ import { getChartIdsInFilterScope } from '../../util/activeDashboardFilters'; import { TIME_FILTER_MAP } from '../../../visualizations/FilterBox/FilterBox'; +import { + NativeFiltersState, + FilterState as NativeFilterState, +} from '../nativeFilters/types'; export enum IndicatorStatus { Unset = 'UNSET', @@ -89,8 +93,9 @@ const selectIndicatorsForChartFromFilter = ( // filters can be applied (if the filter is compatible with the datasource) // or rejected (if the filter is incompatible) // or the status can be unknown (if the filter has calculated parameters that we can't analyze) - const getStatus = (column: string) => { - if (appliedColumns.has(column)) return IndicatorStatus.Applied; + const getStatus = (column: string, filter: Filter) => { + if (appliedColumns.has(column) && filter.columns[column]) + return IndicatorStatus.Applied; if (rejectedColumns.has(column)) return IndicatorStatus.Incompatible; return IndicatorStatus.Unset; }; @@ -105,7 +110,7 @@ const selectIndicatorsForChartFromFilter = ( column, name: filter.labels[column] || column, value: selectIndicatorValue(column, filter, filterDataSource), - status: getStatus(column), + status: getStatus(column, filter), path: filter.directPathToFilter, })); }; @@ -159,3 +164,38 @@ export const selectIndicatorsForChart = ( indicators.sort((a, b) => a.name.localeCompare(b.name)); return indicators; }; + +const selectNativeIndicatorValue = ( + filterState: NativeFilterState, +): string[] => { + const filters = filterState?.extraFormData?.append_form_data?.filters; + if (filters?.length) { + const filter = filters[0]; + if ('val' in filter) { + const val = filter.val as string | string[]; + if (Array.isArray(val)) { + return val; + } + return [val]; + } + } + return []; +}; + +export const selectNativeIndicatorsForChart = ( + nativeFilters: NativeFiltersState, +): Indicator[] => { + const indicators = Object.values(nativeFilters.filters).map(nativeFilter => { + const column = nativeFilter.targets[0].column.name; + const filterState = nativeFilters.filtersState[nativeFilter.id]; + const value = selectNativeIndicatorValue(filterState); + return { + column, + name: nativeFilter.name, + path: [nativeFilter.id], + status: value.length ? IndicatorStatus.Applied : IndicatorStatus.Unset, + value, + }; + }); + return indicators; +}; diff --git a/superset-frontend/src/dashboard/containers/FiltersBadge.tsx b/superset-frontend/src/dashboard/containers/FiltersBadge.tsx index d9535c196f..865abf5e1e 100644 --- a/superset-frontend/src/dashboard/containers/FiltersBadge.tsx +++ b/superset-frontend/src/dashboard/containers/FiltersBadge.tsx @@ -18,10 +18,13 @@ */ import { connect } from 'react-redux'; import { bindActionCreators, Dispatch } from 'redux'; +import { uniqWith } from 'lodash'; import { setDirectPathToChild } from 'src/dashboard/actions/dashboardState'; import { selectIndicatorsForChart, + Indicator, IndicatorStatus, + selectNativeIndicatorsForChart, } from 'src/dashboard/components/FiltersBadge/selectors'; import FiltersBadge from 'src/dashboard/components/FiltersBadge'; @@ -37,17 +40,38 @@ const mapDispatchToProps = (dispatch: Dispatch) => dispatch, ); +const sortByStatus = (indicators: Indicator[]): Indicator[] => { + const statuses = [ + IndicatorStatus.Applied, + IndicatorStatus.Unset, + IndicatorStatus.Incompatible, + ]; + return indicators.sort( + (a, b) => statuses.indexOf(a.status) - statuses.indexOf(b.status), + ); +}; + const mapStateToProps = ( - { datasources, dashboardFilters, charts }: any, + { datasources, dashboardFilters, nativeFilters, charts }: any, { chartId }: FiltersBadgeProps, ) => { - const indicators = selectIndicatorsForChart( + const dashboardIndicators = selectIndicatorsForChart( chartId, dashboardFilters, datasources, charts, ); + const nativeIndicators = selectNativeIndicatorsForChart(nativeFilters); + + const indicators = uniqWith( + sortByStatus([...dashboardIndicators, ...nativeIndicators]), + (ind1, ind2) => + ind1.column === ind2.column && + (ind1.status !== IndicatorStatus.Applied || + ind2.status !== IndicatorStatus.Applied), + ); + const appliedIndicators = indicators.filter( indicator => indicator.status === IndicatorStatus.Applied, );