mirror of
https://github.com/apache/superset.git
synced 2024-09-06 22:07:34 -04:00
feat(cross-filters): add cross filters (#12662)
* feat: add cross filters * refactor: fix CR notes * lint: fix lint * lint: fix lint * chore: pre-commit * refactor: under chage * refactor: move to behaviors * lint: fix lint Co-authored-by: amitmiran137 <amit.miran@nielsen.com>
This commit is contained in:
parent
85d02620b7
commit
956f276e70
@ -27,19 +27,24 @@ import { sliceId as chartId } from '../../../fixtures/mockChartQueries';
|
||||
|
||||
describe('getFormDataWithExtraFilters', () => {
|
||||
const filterId = 'native-filter-1';
|
||||
const mockArgs: GetFormDataWithExtraFiltersArguments = {
|
||||
chart: {
|
||||
id: chartId,
|
||||
formData: {
|
||||
filters: [
|
||||
{
|
||||
col: 'country_name',
|
||||
op: 'IN',
|
||||
val: ['United States'],
|
||||
},
|
||||
],
|
||||
},
|
||||
const mockChart = {
|
||||
id: chartId,
|
||||
formData: {
|
||||
viz_type: 'filter_select',
|
||||
filters: [
|
||||
{
|
||||
col: 'country_name',
|
||||
op: 'IN',
|
||||
val: ['United States'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const mockArgs: GetFormDataWithExtraFiltersArguments = {
|
||||
charts: {
|
||||
[chartId]: mockChart,
|
||||
},
|
||||
chart: mockChart,
|
||||
filters: {
|
||||
region: ['Spain'],
|
||||
color: ['pink', 'purple'],
|
||||
|
@ -22,12 +22,14 @@ import { bindActionCreators } from 'redux';
|
||||
import * as actions from './chartAction';
|
||||
import { logEvent } from '../logger/actions';
|
||||
import Chart from './Chart';
|
||||
import { setExtraFormData } from '../dashboard/actions/nativeFilters';
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(
|
||||
{
|
||||
...actions,
|
||||
setExtraFormData,
|
||||
logEvent,
|
||||
},
|
||||
dispatch,
|
||||
|
@ -42,6 +42,7 @@ const propTypes = {
|
||||
refreshOverlayVisible: PropTypes.bool,
|
||||
// dashboard callbacks
|
||||
addFilter: PropTypes.func,
|
||||
setExtraFormData: PropTypes.func,
|
||||
onFilterMenuOpen: PropTypes.func,
|
||||
onFilterMenuClose: PropTypes.func,
|
||||
};
|
||||
@ -73,6 +74,8 @@ class ChartRenderer extends React.Component {
|
||||
setControlValue: this.handleSetControlValue,
|
||||
onFilterMenuOpen: this.props.onFilterMenuOpen,
|
||||
onFilterMenuClose: this.props.onFilterMenuClose,
|
||||
setExtraFormData: extraFormData =>
|
||||
this.props.actions?.setExtraFormData(this.props.chartId, extraFormData),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,16 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ExtraFormData, QueryFormData, QueryObject } from '@superset-ui/core';
|
||||
import {
|
||||
ExtraFormData,
|
||||
QueryFormData,
|
||||
getChartMetadataRegistry,
|
||||
QueryObject,
|
||||
Behavior,
|
||||
} from '@superset-ui/core';
|
||||
import { Charts } from 'src/dashboard/types';
|
||||
import { RefObject } from 'react';
|
||||
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
|
||||
import { Filter } from './types';
|
||||
import { NativeFiltersState } from '../../reducers/types';
|
||||
|
||||
@ -93,8 +101,16 @@ export function mergeExtraFormData(
|
||||
};
|
||||
}
|
||||
|
||||
export function isCrossFilter(vizType: string) {
|
||||
// @ts-ignore need export from superset-ui `ItemWithValue`
|
||||
return getChartMetadataRegistry().items[vizType]?.value.behaviors?.includes(
|
||||
Behavior.CROSS_FILTER,
|
||||
);
|
||||
}
|
||||
|
||||
export function getExtraFormData(
|
||||
nativeFilters: NativeFiltersState,
|
||||
charts: Charts,
|
||||
): ExtraFormData {
|
||||
let extraFormData: ExtraFormData = {};
|
||||
Object.keys(nativeFilters.filters).forEach(key => {
|
||||
@ -102,5 +118,14 @@ export function getExtraFormData(
|
||||
const { extraFormData: newExtra = {} } = filterState;
|
||||
extraFormData = mergeExtraFormData(extraFormData, newExtra);
|
||||
});
|
||||
if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) {
|
||||
Object.entries(charts).forEach(([key, chart]) => {
|
||||
if (isCrossFilter(chart?.formData?.viz_type)) {
|
||||
const filterState = nativeFilters.filtersState[key] || {};
|
||||
const { extraFormData: newExtra = {} } = filterState;
|
||||
extraFormData = mergeExtraFormData(extraFormData, newExtra);
|
||||
}
|
||||
});
|
||||
}
|
||||
return extraFormData;
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ function mapStateToProps(
|
||||
const formData = getFormDataWithExtraFilters({
|
||||
layout: dashboardLayout.present,
|
||||
chart,
|
||||
charts: chartQueries,
|
||||
filters: getAppliedFilterValues(id),
|
||||
colorScheme,
|
||||
colorNamespace,
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
CategoricalColorNamespace,
|
||||
DataRecordFilters,
|
||||
} from '@superset-ui/core';
|
||||
import { ChartQueryPayload, LayoutItem } from 'src/dashboard/types';
|
||||
import { ChartQueryPayload, Charts, LayoutItem } from 'src/dashboard/types';
|
||||
import { getExtraFormData } from 'src/dashboard/components/nativeFilters/utils';
|
||||
import getEffectiveExtraFilters from './getEffectiveExtraFilters';
|
||||
import { getActiveNativeFilters } from '../activeDashboardNativeFilters';
|
||||
@ -34,6 +34,7 @@ const cachedFormdataByChart = {};
|
||||
|
||||
export interface GetFormDataWithExtraFiltersArguments {
|
||||
chart: ChartQueryPayload;
|
||||
charts: Charts;
|
||||
filters: DataRecordFilters;
|
||||
layout: { [key: string]: LayoutItem };
|
||||
colorScheme?: string;
|
||||
@ -47,6 +48,7 @@ export interface GetFormDataWithExtraFiltersArguments {
|
||||
// filters param only contains those applicable to this chart.
|
||||
export default function getFormDataWithExtraFilters({
|
||||
chart,
|
||||
charts,
|
||||
filters,
|
||||
colorScheme,
|
||||
colorNamespace,
|
||||
@ -78,7 +80,7 @@ export default function getFormDataWithExtraFilters({
|
||||
);
|
||||
if (isAffectedChart) {
|
||||
extraData = {
|
||||
extra_form_data: getExtraFormData(nativeFilters),
|
||||
extra_form_data: getExtraFormData(nativeFilters, charts),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,9 @@ import { useDynamicPluginContext } from 'src/components/DynamicPlugins';
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Label from 'src/components/Label';
|
||||
|
||||
import ControlHeader from '../ControlHeader';
|
||||
import './VizTypeControl.less';
|
||||
import { FeatureFlag, isFeatureEnabled } from '../../../featureFlags';
|
||||
|
||||
const propTypes = {
|
||||
description: PropTypes.string,
|
||||
@ -168,7 +168,11 @@ const VizTypeControl = props => {
|
||||
const filteredTypes = DEFAULT_ORDER.filter(type => registry.has(type))
|
||||
.filter(type => {
|
||||
const behaviors = registry.get(type)?.behaviors || [];
|
||||
return behaviors.includes(Behavior.CROSS_FILTER) || !behaviors.length;
|
||||
return (
|
||||
(isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS) &&
|
||||
behaviors.includes(Behavior.CROSS_FILTER)) ||
|
||||
!behaviors.length
|
||||
);
|
||||
})
|
||||
.map(type => ({
|
||||
key: type,
|
||||
@ -179,7 +183,11 @@ const VizTypeControl = props => {
|
||||
.entries()
|
||||
.filter(entry => {
|
||||
const behaviors = entry.value?.behaviors || [];
|
||||
return behaviors.includes(Behavior.CROSS_FILTER) || !behaviors.length;
|
||||
return (
|
||||
(isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS) &&
|
||||
behaviors.includes(Behavior.CROSS_FILTER)) ||
|
||||
!behaviors.length
|
||||
);
|
||||
})
|
||||
.filter(({ key }) => !typesWithDefaultOrder.has(key)),
|
||||
)
|
||||
|
@ -35,6 +35,7 @@ export enum FeatureFlag {
|
||||
DISPLAY_MARKDOWN_HTML = 'DISPLAY_MARKDOWN_HTML',
|
||||
ESCAPE_MARKDOWN_HTML = 'ESCAPE_MARKDOWN_HTML',
|
||||
DASHBOARD_NATIVE_FILTERS = 'DASHBOARD_NATIVE_FILTERS',
|
||||
DASHBOARD_CROSS_FILTERS = 'DASHBOARD_CROSS_FILTERS',
|
||||
VERSIONED_EXPORT = 'VERSIONED_EXPORT',
|
||||
GLOBAL_ASYNC_QUERIES = 'GLOBAL_ASYNC_QUERIES',
|
||||
ENABLE_TEMPLATE_PROCESSING = 'ENABLE_TEMPLATE_PROCESSING',
|
||||
|
@ -328,6 +328,7 @@ DEFAULT_FEATURE_FLAGS: Dict[str, bool] = {
|
||||
# When True, this escapes HTML (rather than rendering it) in Markdown components
|
||||
"ESCAPE_MARKDOWN_HTML": False,
|
||||
"DASHBOARD_NATIVE_FILTERS": False,
|
||||
"DASHBOARD_CROSS_FILTERS": False,
|
||||
"GLOBAL_ASYNC_QUERIES": False,
|
||||
"VERSIONED_EXPORT": False,
|
||||
# Note that: RowLevelSecurityFilter is only given by default to the Admin role
|
||||
|
Loading…
Reference in New Issue
Block a user