Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Cross filters scoping #24020

Merged
merged 11 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions superset-frontend/src/components/DropdownSelectableIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,25 @@ const StyleSubmenuItem = styled.div`
export default (props: DropDownSelectableProps) => {
const theme = useTheme();
const { icon, info, menuItems, selectedKeys, onSelect } = props;
const menuItem = (
label: string | React.ReactNode,
key: string,
divider?: boolean,
) => (
<StyleMenuItem key={key} divider={divider}>
<StyleSubmenuItem>
<span>{label}</span>
{selectedKeys?.includes(key) && (
<Icons.Check
iconColor={theme.colors.primary.base}
className="tick-menu-item"
iconSize="xl"
/>
)}
</StyleSubmenuItem>
</StyleMenuItem>
const menuItem = useMemo(
() => (label: string | React.ReactNode, key: string, divider?: boolean) =>
(
<StyleMenuItem key={key} divider={divider}>
<StyleSubmenuItem>
<span>{label}</span>
{selectedKeys?.includes(key) && (
<Icons.Check
iconColor={theme.colors.primary.base}
className="tick-menu-item"
iconSize="xl"
/>
)}
</StyleSubmenuItem>
</StyleMenuItem>
),
[selectedKeys, theme.colors.primary.base],
);

const overlayMenu = useMemo(
() => (
<StyledMenu selectedKeys={selectedKeys} onSelect={onSelect} selectable>
Expand All @@ -141,7 +142,7 @@ export default (props: DropDownSelectableProps) => {
)}
</StyledMenu>
),
[info, menuItems],
[selectedKeys, onSelect, info, menuItems, menuItem],
);

return (
Expand Down
15 changes: 11 additions & 4 deletions superset-frontend/src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useMemo, useRef, useState } from 'react';
import React, {
CSSProperties,
ReactNode,
useMemo,
useRef,
useState,
} from 'react';
import { isNil } from 'lodash';
import { ModalFuncProps } from 'antd/lib/modal';
import { styled, t } from '@superset-ui/core';
Expand All @@ -33,7 +39,7 @@ import Draggable, {

export interface ModalProps {
className?: string;
children: React.ReactNode;
children: ReactNode;
disablePrimaryButton?: boolean;
primaryButtonLoading?: boolean;
onHide: () => void;
Expand All @@ -42,13 +48,13 @@ export interface ModalProps {
primaryButtonType?: 'primary' | 'danger';
show: boolean;
name?: string;
title: React.ReactNode;
title: ReactNode;
width?: string;
maxWidth?: string;
responsive?: boolean;
hideFooter?: boolean;
centered?: boolean;
footer?: React.ReactNode;
footer?: ReactNode;
wrapProps?: object;
height?: string;
closable?: boolean;
Expand All @@ -59,6 +65,7 @@ export interface ModalProps {
destroyOnClose?: boolean;
maskClosable?: boolean;
zIndex?: number;
bodyStyle?: CSSProperties;
}

interface StyledModalProps {
Expand Down
54 changes: 27 additions & 27 deletions superset-frontend/src/dashboard/actions/dashboardInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
* under the License.
*/
import { Dispatch } from 'redux';
import { makeApi, CategoricalColorNamespace } from '@superset-ui/core';
import { makeApi, CategoricalColorNamespace, t } from '@superset-ui/core';
import { isString } from 'lodash';
import { getErrorText } from 'src/utils/getClientErrorObject';
import { addDangerToast } from 'src/components/MessageToasts/actions';
import {
ChartConfiguration,
DashboardInfo,
FilterBarOrientation,
GlobalChartCrossFilterConfig,
RootState,
} from 'src/dashboard/types';
import { ChartConfiguration } from 'src/dashboard/reducers/types';
import { onSave } from './dashboardState';

export const DASHBOARD_INFO_UPDATED = 'DASHBOARD_INFO_UPDATED';
Expand Down Expand Up @@ -67,26 +68,22 @@ export function dashboardInfoChanged(newInfo: { metadata: any }) {
return { type: DASHBOARD_INFO_UPDATED, newInfo };
}
export const SET_CHART_CONFIG_BEGIN = 'SET_CHART_CONFIG_BEGIN';
export interface SetChartConfigBegin {
type: typeof SET_CHART_CONFIG_BEGIN;
chartConfiguration: ChartConfiguration;
}
export const SET_CHART_CONFIG_COMPLETE = 'SET_CHART_CONFIG_COMPLETE';
export interface SetChartConfigComplete {
type: typeof SET_CHART_CONFIG_COMPLETE;
chartConfiguration: ChartConfiguration;
}
export const SET_CHART_CONFIG_FAIL = 'SET_CHART_CONFIG_FAIL';
export interface SetChartConfigFail {
type: typeof SET_CHART_CONFIG_FAIL;
chartConfiguration: ChartConfiguration;
}
export const setChartConfiguration =
(chartConfiguration: ChartConfiguration) =>
async (dispatch: Dispatch, getState: () => any) => {

export const saveChartConfiguration =
({
chartConfiguration,
globalChartConfiguration,
}: {
chartConfiguration?: ChartConfiguration;
globalChartConfiguration?: GlobalChartCrossFilterConfig;
}) =>
async (dispatch: Dispatch, getState: () => RootState) => {
dispatch({
type: SET_CHART_CONFIG_BEGIN,
chartConfiguration,
globalChartConfiguration,
});
const { id, metadata } = getState().dashboardInfo;

Expand All @@ -103,7 +100,10 @@ export const setChartConfiguration =
const response = await updateDashboard({
json_metadata: JSON.stringify({
...metadata,
chart_configuration: chartConfiguration,
chart_configuration:
chartConfiguration ?? metadata.chart_configuration,
global_chart_configuration:
globalChartConfiguration ?? metadata.global_chart_configuration,
}),
});
dispatch(
Expand All @@ -114,28 +114,28 @@ export const setChartConfiguration =
dispatch({
type: SET_CHART_CONFIG_COMPLETE,
chartConfiguration,
globalChartConfiguration,
});
} catch (err) {
dispatch({ type: SET_CHART_CONFIG_FAIL, chartConfiguration });
dispatch({
type: SET_CHART_CONFIG_FAIL,
villebro marked this conversation as resolved.
Show resolved Hide resolved
chartConfiguration,
globalChartConfiguration,
});
dispatch(addDangerToast(t('Failed to save cross-filter scoping')));
}
};

export const SET_FILTER_BAR_ORIENTATION = 'SET_FILTER_BAR_ORIENTATION';
export interface SetFilterBarOrientation {
type: typeof SET_FILTER_BAR_ORIENTATION;
filterBarOrientation: FilterBarOrientation;
}

export function setFilterBarOrientation(
filterBarOrientation: FilterBarOrientation,
) {
return { type: SET_FILTER_BAR_ORIENTATION, filterBarOrientation };
}

export const SET_CROSS_FILTERS_ENABLED = 'SET_CROSS_FILTERS_ENABLED';
export interface SetCrossFiltersEnabled {
type: typeof SET_CROSS_FILTERS_ENABLED;
crossFiltersEnabled: boolean;
}

export function setCrossFiltersEnabled(crossFiltersEnabled: boolean) {
return { type: SET_CROSS_FILTERS_ENABLED, crossFiltersEnabled };
}
Expand Down
32 changes: 15 additions & 17 deletions superset-frontend/src/dashboard/actions/dashboardState.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import { logEvent } from 'src/logger/actions';
import { LOG_ACTIONS_CONFIRM_OVERWRITE_DASHBOARD_METADATA } from 'src/logger/LogUtils';
import { UPDATE_COMPONENTS_PARENTS_LIST } from './dashboardLayout';
import {
setChartConfiguration,
saveChartConfiguration,
dashboardInfoChanged,
SET_CHART_CONFIG_COMPLETE,
} from './dashboardInfo';
Expand Down Expand Up @@ -89,7 +89,6 @@ export function toggleFaveStar(isStarred) {
return { type: TOGGLE_FAVE_STAR, isStarred };
}

export const FETCH_FAVE_STAR = 'FETCH_FAVE_STAR';
export function fetchFaveStar(id) {
return function fetchFaveStarThunk(dispatch) {
return SupersetClient.get({
Expand All @@ -110,7 +109,6 @@ export function fetchFaveStar(id) {
};
}

export const SAVE_FAVE_STAR = 'SAVE_FAVE_STAR';
export function saveFaveStar(id, isStarred) {
return function saveFaveStarThunk(dispatch) {
const endpoint = `/api/v1/dashboard/${id}/favorites/`;
Expand Down Expand Up @@ -287,13 +285,11 @@ export function saveDashboardRequest(data, id, saveType) {
const {
dashboardLayout,
charts,
dashboardInfo: {
metadata: { chart_configuration = {} },
},
dashboardInfo: { metadata },
} = getState();
return getCrossFiltersConfiguration(
dashboardLayout.present,
chart_configuration,
metadata,
charts,
);
};
Expand All @@ -304,8 +300,14 @@ export function saveDashboardRequest(data, id, saveType) {
dispatch(saveDashboardRequestSuccess(lastModifiedTime));
}
if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) {
const chartConfiguration = handleChartConfiguration();
dispatch(setChartConfiguration(chartConfiguration));
const { chartConfiguration, globalChartConfiguration } =
handleChartConfiguration();
dispatch(
saveChartConfiguration({
chartConfiguration,
globalChartConfiguration,
}),
);
}
dispatch(saveDashboardFinished());
dispatch(addSuccessToast(t('This dashboard was saved successfully.')));
Expand Down Expand Up @@ -373,8 +375,10 @@ export function saveDashboardRequest(data, id, saveType) {
[SAVE_TYPE_OVERWRITE, SAVE_TYPE_OVERWRITE_CONFIRMED].includes(saveType)
) {
let chartConfiguration = {};
let globalChartConfiguration = {};
if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) {
chartConfiguration = handleChartConfiguration();
({ chartConfiguration, globalChartConfiguration } =
handleChartConfiguration());
}
const updatedDashboard =
saveType === SAVE_TYPE_OVERWRITE_CONFIRMED
Expand All @@ -392,6 +396,7 @@ export function saveDashboardRequest(data, id, saveType) {
default_filters: safeStringify(serializedFilters),
filter_scopes: serializedFilterScopes,
chart_configuration: chartConfiguration,
global_chart_configuration: globalChartConfiguration,
}),
};

Expand Down Expand Up @@ -601,13 +606,6 @@ export function setColorScheme(colorScheme) {
return { type: SET_COLOR_SCHEME, colorScheme };
}

export function setColorSchemeAndUnsavedChanges(colorScheme) {
return dispatch => {
dispatch(setColorScheme(colorScheme));
dispatch(setUnsavedChanges(true));
};
}

export const SET_DIRECT_PATH = 'SET_DIRECT_PATH';
export function setDirectPathToChild(path) {
return { type: SET_DIRECT_PATH, path };
Expand Down
13 changes: 8 additions & 5 deletions superset-frontend/src/dashboard/actions/hydrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,14 @@ export const hydrateDashboard =
});

if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) {
metadata.chart_configuration = getCrossFiltersConfiguration(
dashboardLayout.present,
metadata.chart_configuration,
chartQueries,
);
const { chartConfiguration, globalChartConfiguration } =
getCrossFiltersConfiguration(
dashboardLayout.present,
metadata,
chartQueries,
);
metadata.chart_configuration = chartConfiguration;
metadata.global_chart_configuration = globalChartConfiguration;
}

const { roles } = user;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import pick from 'lodash/pick';
import Tabs from 'src/components/Tabs';
import DashboardGrid from 'src/dashboard/containers/DashboardGrid';
import {
ChartsState,
DashboardInfo,
DashboardLayout,
LayoutItem,
Expand Down Expand Up @@ -86,7 +85,9 @@ const DashboardContainer: FC<DashboardContainerProps> = ({ topLevelTabs }) => {
const directPathToChild = useSelector<RootState, string[]>(
state => state.dashboardState.directPathToChild,
);
const charts = useSelector<RootState, ChartsState>(state => state.charts);
const chartIds = useSelector<RootState, number[]>(state =>
Object.values(state.charts).map(chart => chart.id),
);

const tabIndex = useMemo(() => {
const nextTabIndex = findTabIndexByComponentId({
Expand Down Expand Up @@ -116,7 +117,7 @@ const DashboardContainer: FC<DashboardContainerProps> = ({ topLevelTabs }) => {
}
const chartsInScope: number[] = getChartIdsInFilterScope(
filterScope.scope,
charts,
chartIds,
dashboardLayout,
);
const tabsInScope = findTabsWithChartsInScope(
Expand Down Expand Up @@ -207,7 +208,7 @@ const DashboardContainer: FC<DashboardContainerProps> = ({ topLevelTabs }) => {
}
}
}
}, [charts]);
}, [chartIds]);

useComponentDidUpdate(verifyUpdateColorScheme);

Expand Down
Loading