chore: Removing DASHBOARD_CROSS_FILTERS flag and all that comes with it. (#31794)
Co-authored-by: Kamil Gabryjelski <kamil.gabryjelski@gmail.com>
This commit is contained in:
parent
640d4f09bd
commit
962fd4cca3
|
|
@ -97,7 +97,6 @@ These features flags currently default to True and **will be removed in a future
|
||||||
[//]: # "PLEASE KEEP THE LIST SORTED ALPHABETICALLY"
|
[//]: # "PLEASE KEEP THE LIST SORTED ALPHABETICALLY"
|
||||||
|
|
||||||
- AVOID_COLORS_COLLISION
|
- AVOID_COLORS_COLLISION
|
||||||
- DASHBOARD_CROSS_FILTERS
|
|
||||||
- DRILL_TO_DETAIL
|
- DRILL_TO_DETAIL
|
||||||
- ENABLE_JAVASCRIPT_CONTROLS
|
- ENABLE_JAVASCRIPT_CONTROLS
|
||||||
- KV_STORE
|
- KV_STORE
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ assists people when migrating to a new version.
|
||||||
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: /api/v1/database/<id>/<file type>_upload and /api/v1/database/<file type>_metadata, in favour of new one (Details on the PR). And simplifies permissions.
|
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: /api/v1/database/<id>/<file type>_upload and /api/v1/database/<file type>_metadata, in favour of new one (Details on the PR). And simplifies permissions.
|
||||||
- [31844](https://github.com/apache/superset/pull/31844) The `ALERT_REPORTS_EXECUTE_AS` and `THUMBNAILS_EXECUTE_AS` config parameters have been renamed to `ALERT_REPORTS_EXECUTORS` and `THUMBNAILS_EXECUTORS` respectively. A new config flag `CACHE_WARMUP_EXECUTORS` has also been introduced to be able to control which user is used to execute cache warmup tasks. Finally, the config flag `THUMBNAILS_SELENIUM_USER` has been removed. To use a fixed executor for async tasks, use the new `FixedExecutor` class. See the config and docs for more info on setting up different executor profiles.
|
- [31844](https://github.com/apache/superset/pull/31844) The `ALERT_REPORTS_EXECUTE_AS` and `THUMBNAILS_EXECUTE_AS` config parameters have been renamed to `ALERT_REPORTS_EXECUTORS` and `THUMBNAILS_EXECUTORS` respectively. A new config flag `CACHE_WARMUP_EXECUTORS` has also been introduced to be able to control which user is used to execute cache warmup tasks. Finally, the config flag `THUMBNAILS_SELENIUM_USER` has been removed. To use a fixed executor for async tasks, use the new `FixedExecutor` class. See the config and docs for more info on setting up different executor profiles.
|
||||||
- [31894](https://github.com/apache/superset/pull/31894) Domain sharding is deprecated in favor of HTTP2. The `SUPERSET_WEBSERVER_DOMAINS` configuration will be removed in the next major version (6.0)
|
- [31894](https://github.com/apache/superset/pull/31894) Domain sharding is deprecated in favor of HTTP2. The `SUPERSET_WEBSERVER_DOMAINS` configuration will be removed in the next major version (6.0)
|
||||||
|
- [31794](https://github.com/apache/superset/pull/31794) Removed the previously deprecated `DASHBOARD_CROSS_FILTERS` feature flag
|
||||||
- [31774](https://github.com/apache/superset/pull/31774): Fixes the spelling of the `USE-ANALAGOUS-COLORS` feature flag. Please update any scripts/configuration item to use the new/corrected `USE-ANALOGOUS-COLORS` flag spelling.
|
- [31774](https://github.com/apache/superset/pull/31774): Fixes the spelling of the `USE-ANALAGOUS-COLORS` feature flag. Please update any scripts/configuration item to use the new/corrected `USE-ANALOGOUS-COLORS` flag spelling.
|
||||||
- [31582](https://github.com/apache/superset/pull/31582) Removed the legacy Area, Bar, Event Flow, Heatmap, Histogram, Line, Sankey, and Sankey Loop charts. They were all automatically migrated to their ECharts counterparts with the exception of the Event Flow and Sankey Loop charts which were removed as they were not actively maintained and not widely used. If you were using the Event Flow or Sankey Loop charts, you will need to find an alternative solution.
|
- [31582](https://github.com/apache/superset/pull/31582) Removed the legacy Area, Bar, Event Flow, Heatmap, Histogram, Line, Sankey, and Sankey Loop charts. They were all automatically migrated to their ECharts counterparts with the exception of the Event Flow and Sankey Loop charts which were removed as they were not actively maintained and not widely used. If you were using the Event Flow or Sankey Loop charts, you will need to find an alternative solution.
|
||||||
- [31198](https://github.com/apache/superset/pull/31198) Disallows by default the use of the following ClickHouse functions: "version", "currentDatabase", "hostName".
|
- [31198](https://github.com/apache/superset/pull/31198) Disallows by default the use of the following ClickHouse functions: "version", "currentDatabase", "hostName".
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,6 @@ export enum FeatureFlag {
|
||||||
AvoidColorsCollision = 'AVOID_COLORS_COLLISION',
|
AvoidColorsCollision = 'AVOID_COLORS_COLLISION',
|
||||||
ChartPluginsExperimental = 'CHART_PLUGINS_EXPERIMENTAL',
|
ChartPluginsExperimental = 'CHART_PLUGINS_EXPERIMENTAL',
|
||||||
ConfirmDashboardDiff = 'CONFIRM_DASHBOARD_DIFF',
|
ConfirmDashboardDiff = 'CONFIRM_DASHBOARD_DIFF',
|
||||||
/** @deprecated */
|
|
||||||
DashboardCrossFilters = 'DASHBOARD_CROSS_FILTERS',
|
|
||||||
DashboardVirtualization = 'DASHBOARD_VIRTUALIZATION',
|
DashboardVirtualization = 'DASHBOARD_VIRTUALIZATION',
|
||||||
DashboardRbac = 'DASHBOARD_RBAC',
|
DashboardRbac = 'DASHBOARD_RBAC',
|
||||||
DatapanelClosedByDefault = 'DATAPANEL_CLOSED_BY_DEFAULT',
|
DatapanelClosedByDefault = 'DATAPANEL_CLOSED_BY_DEFAULT',
|
||||||
|
|
|
||||||
|
|
@ -127,9 +127,7 @@ const ChartContextMenu = (
|
||||||
canDrillBy &&
|
canDrillBy &&
|
||||||
isDisplayed(ContextMenuItem.DrillBy);
|
isDisplayed(ContextMenuItem.DrillBy);
|
||||||
|
|
||||||
const showCrossFilters =
|
const showCrossFilters = isDisplayed(ContextMenuItem.CrossFilter);
|
||||||
isFeatureEnabled(FeatureFlag.DashboardCrossFilters) &&
|
|
||||||
isDisplayed(ContextMenuItem.CrossFilter);
|
|
||||||
|
|
||||||
const isCrossFilteringSupportedByChart = getChartMetadataRegistry()
|
const isCrossFilteringSupportedByChart = getChartMetadataRegistry()
|
||||||
.get(formData.viz_type)
|
.get(formData.viz_type)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ const CONTEXT_MENU_TEST_ID = 'chart-context-menu';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
global.featureFlags = {
|
global.featureFlags = {
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
[FeatureFlag.DrillToDetail]: true,
|
[FeatureFlag.DrillToDetail]: true,
|
||||||
[FeatureFlag.DrillBy]: true,
|
[FeatureFlag.DrillBy]: true,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ import {
|
||||||
logging,
|
logging,
|
||||||
Behavior,
|
Behavior,
|
||||||
t,
|
t,
|
||||||
isFeatureEnabled,
|
|
||||||
FeatureFlag,
|
|
||||||
getChartMetadataRegistry,
|
getChartMetadataRegistry,
|
||||||
VizType,
|
VizType,
|
||||||
|
isFeatureEnabled,
|
||||||
|
FeatureFlag,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils';
|
import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils';
|
||||||
import { EmptyState } from 'src/components/EmptyState';
|
import { EmptyState } from 'src/components/EmptyState';
|
||||||
|
|
@ -92,8 +92,7 @@ class ChartRenderer extends Component {
|
||||||
showContextMenu:
|
showContextMenu:
|
||||||
props.source === ChartSource.Dashboard &&
|
props.source === ChartSource.Dashboard &&
|
||||||
!suppressContextMenu &&
|
!suppressContextMenu &&
|
||||||
(isFeatureEnabled(FeatureFlag.DrillToDetail) ||
|
isFeatureEnabled(FeatureFlag.DrillToDetail),
|
||||||
isFeatureEnabled(FeatureFlag.DashboardCrossFilters)),
|
|
||||||
inContextMenu: false,
|
inContextMenu: false,
|
||||||
legendState: undefined,
|
legendState: undefined,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,6 @@ export function saveDashboardRequest(data, id, saveType) {
|
||||||
if (lastModifiedTime) {
|
if (lastModifiedTime) {
|
||||||
dispatch(saveDashboardRequestSuccess(lastModifiedTime));
|
dispatch(saveDashboardRequestSuccess(lastModifiedTime));
|
||||||
}
|
}
|
||||||
if (isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
const { chartConfiguration, globalChartConfiguration } =
|
const { chartConfiguration, globalChartConfiguration } =
|
||||||
handleChartConfiguration();
|
handleChartConfiguration();
|
||||||
dispatch(
|
dispatch(
|
||||||
|
|
@ -362,7 +361,6 @@ export function saveDashboardRequest(data, id, saveType) {
|
||||||
globalChartConfiguration,
|
globalChartConfiguration,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
dispatch(saveDashboardFinished());
|
dispatch(saveDashboardFinished());
|
||||||
dispatch(addSuccessToast(t('This dashboard was saved successfully.')));
|
dispatch(addSuccessToast(t('This dashboard was saved successfully.')));
|
||||||
return response;
|
return response;
|
||||||
|
|
@ -435,12 +433,8 @@ export function saveDashboardRequest(data, id, saveType) {
|
||||||
if (
|
if (
|
||||||
[SAVE_TYPE_OVERWRITE, SAVE_TYPE_OVERWRITE_CONFIRMED].includes(saveType)
|
[SAVE_TYPE_OVERWRITE, SAVE_TYPE_OVERWRITE_CONFIRMED].includes(saveType)
|
||||||
) {
|
) {
|
||||||
let chartConfiguration = {};
|
const { chartConfiguration, globalChartConfiguration } =
|
||||||
let globalChartConfiguration = {};
|
handleChartConfiguration();
|
||||||
if (isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
({ chartConfiguration, globalChartConfiguration } =
|
|
||||||
handleChartConfiguration());
|
|
||||||
}
|
|
||||||
const updatedDashboard =
|
const updatedDashboard =
|
||||||
saveType === SAVE_TYPE_OVERWRITE_CONFIRMED
|
saveType === SAVE_TYPE_OVERWRITE_CONFIRMED
|
||||||
? data
|
? data
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ describe('dashboardState actions', () => {
|
||||||
present: mockDashboardData.positions,
|
present: mockDashboardData.positions,
|
||||||
future: {},
|
future: {},
|
||||||
},
|
},
|
||||||
|
charts: {},
|
||||||
};
|
};
|
||||||
const newDashboardData = mockDashboardData;
|
const newDashboardData = mockDashboardData;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,6 @@ export const hydrateDashboard =
|
||||||
filterConfig: metadata?.native_filter_configuration || [],
|
filterConfig: metadata?.native_filter_configuration || [],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
const { chartConfiguration, globalChartConfiguration } =
|
const { chartConfiguration, globalChartConfiguration } =
|
||||||
getCrossFiltersConfiguration(
|
getCrossFiltersConfiguration(
|
||||||
dashboardLayout.present,
|
dashboardLayout.present,
|
||||||
|
|
@ -239,7 +238,6 @@ export const hydrateDashboard =
|
||||||
);
|
);
|
||||||
metadata.chart_configuration = chartConfiguration;
|
metadata.chart_configuration = chartConfiguration;
|
||||||
metadata.global_chart_configuration = globalChartConfiguration;
|
metadata.global_chart_configuration = globalChartConfiguration;
|
||||||
}
|
|
||||||
|
|
||||||
const { roles } = user;
|
const { roles } = user;
|
||||||
const canEdit = canUserEditDashboard(dashboard, user);
|
const canEdit = canUserEditDashboard(dashboard, user);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { isFeatureEnabled, t, FeatureFlag } from '@superset-ui/core';
|
import { t } from '@superset-ui/core';
|
||||||
|
|
||||||
import { PluginContext } from 'src/components/DynamicPlugins';
|
import { PluginContext } from 'src/components/DynamicPlugins';
|
||||||
import Loading from 'src/components/Loading';
|
import Loading from 'src/components/Loading';
|
||||||
|
|
@ -163,10 +163,7 @@ class Dashboard extends PureComponent {
|
||||||
editMode,
|
editMode,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { appliedFilters, appliedOwnDataCharts } = this;
|
const { appliedFilters, appliedOwnDataCharts } = this;
|
||||||
if (
|
if (!chartConfiguration) {
|
||||||
isFeatureEnabled(FeatureFlag.DashboardCrossFilters) &&
|
|
||||||
!chartConfiguration
|
|
||||||
) {
|
|
||||||
// For a first loading we need to wait for cross filters charts data loaded to get all active filters
|
// For a first loading we need to wait for cross filters charts data loaded to get all active filters
|
||||||
// for correct comparing of filters to avoid unnecessary requests
|
// for correct comparing of filters to avoid unnecessary requests
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ describe('Dashboard', () => {
|
||||||
userId: dashboardInfo.userId,
|
userId: dashboardInfo.userId,
|
||||||
impressionId: 'id',
|
impressionId: 'id',
|
||||||
loadStats: {},
|
loadStats: {},
|
||||||
|
chartConfiguration: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ChildrenComponent = () => <div>Test</div>;
|
const ChildrenComponent = () => <div>Test</div>;
|
||||||
|
|
|
||||||
|
|
@ -396,9 +396,6 @@ const DashboardBuilder = () => {
|
||||||
const fullSizeChartId = useSelector<RootState, number | null>(
|
const fullSizeChartId = useSelector<RootState, number | null>(
|
||||||
state => state.dashboardState.fullSizeChartId,
|
state => state.dashboardState.fullSizeChartId,
|
||||||
);
|
);
|
||||||
const crossFiltersEnabled = isFeatureEnabled(
|
|
||||||
FeatureFlag.DashboardCrossFilters,
|
|
||||||
);
|
|
||||||
const filterBarOrientation = useSelector<RootState, FilterBarOrientation>(
|
const filterBarOrientation = useSelector<RootState, FilterBarOrientation>(
|
||||||
({ dashboardInfo }) =>
|
({ dashboardInfo }) =>
|
||||||
isFeatureEnabled(FeatureFlag.HorizontalFilterBar)
|
isFeatureEnabled(FeatureFlag.HorizontalFilterBar)
|
||||||
|
|
@ -476,8 +473,7 @@ const DashboardBuilder = () => {
|
||||||
ELEMENT_ON_SCREEN_OPTIONS,
|
ELEMENT_ON_SCREEN_OPTIONS,
|
||||||
);
|
);
|
||||||
|
|
||||||
const showFilterBar =
|
const showFilterBar = !editMode;
|
||||||
(crossFiltersEnabled || nativeFiltersEnabled) && !editMode;
|
|
||||||
|
|
||||||
const offset =
|
const offset =
|
||||||
FILTER_BAR_HEADER_HEIGHT +
|
FILTER_BAR_HEADER_HEIGHT +
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,10 @@ test('requests update dashboard api when save button is clicked', async () => {
|
||||||
result: overwriteConfirmMetadata.data,
|
result: overwriteConfirmMetadata.data,
|
||||||
});
|
});
|
||||||
const store = mockStore({
|
const store = mockStore({
|
||||||
dashboardLayout: {},
|
dashboardLayout: { present: {} },
|
||||||
dashboardFilters: {},
|
dashboardFilters: {},
|
||||||
|
dashboardInfo: { metadata: {} },
|
||||||
|
charts: {},
|
||||||
});
|
});
|
||||||
const { findByTestId } = render(
|
const { findByTestId } = render(
|
||||||
<OverwriteConfirmModal
|
<OverwriteConfirmModal
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,6 @@ const SliceHeaderControls = (
|
||||||
useSelector<RootState, boolean>(
|
useSelector<RootState, boolean>(
|
||||||
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
|
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
|
||||||
) &&
|
) &&
|
||||||
isFeatureEnabled(FeatureFlag.DashboardCrossFilters) &&
|
|
||||||
getChartMetadataRegistry()
|
getChartMetadataRegistry()
|
||||||
.get(props.slice.viz_type)
|
.get(props.slice.viz_type)
|
||||||
?.behaviors?.includes(Behavior.InteractiveChart);
|
?.behaviors?.includes(Behavior.InteractiveChart);
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ const setup = (dashboardInfoOverride: Partial<DashboardInfo> = {}) =>
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchMock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
test('Dropdown trigger renders with FF HORIZONTAL_FILTER_BAR on', async () => {
|
test('Dropdown trigger renders with FF HORIZONTAL_FILTER_BAR on', async () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
global.featureFlags = {
|
global.featureFlags = {
|
||||||
|
|
@ -104,33 +108,7 @@ test('Dropdown trigger does not render without dashboard edit permissions', asyn
|
||||||
expect(screen.queryByRole('img', { name: 'gear' })).not.toBeInTheDocument();
|
expect(screen.queryByRole('img', { name: 'gear' })).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Dropdown trigger renders with FF DASHBOARD_CROSS_FILTERS on', async () => {
|
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
};
|
|
||||||
await setup();
|
|
||||||
|
|
||||||
expect(screen.getByRole('img', { name: 'gear' })).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Dropdown trigger does not render with FF DASHBOARD_CROSS_FILTERS off', async () => {
|
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: false,
|
|
||||||
};
|
|
||||||
await setup({
|
|
||||||
dash_edit_perm: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.queryByRole('img', { name: 'gear' })).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Popover shows cross-filtering option on by default', async () => {
|
test('Popover shows cross-filtering option on by default', async () => {
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
};
|
|
||||||
await setup();
|
await setup();
|
||||||
userEvent.click(screen.getByLabelText('gear'));
|
userEvent.click(screen.getByLabelText('gear'));
|
||||||
expect(screen.getByText('Enable cross-filtering')).toBeInTheDocument();
|
expect(screen.getByText('Enable cross-filtering')).toBeInTheDocument();
|
||||||
|
|
@ -138,11 +116,6 @@ test('Popover shows cross-filtering option on by default', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can enable/disable cross-filtering', async () => {
|
test('Can enable/disable cross-filtering', async () => {
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
};
|
|
||||||
fetchMock.reset();
|
|
||||||
fetchMock.put('glob:*/api/v1/dashboard/1', {
|
fetchMock.put('glob:*/api/v1/dashboard/1', {
|
||||||
result: {},
|
result: {},
|
||||||
});
|
});
|
||||||
|
|
@ -168,7 +141,7 @@ test('Popover opens with "Vertical" selected', async () => {
|
||||||
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[2]).getByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[4]).getByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -183,7 +156,7 @@ test('Popover opens with "Horizontal" selected', async () => {
|
||||||
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[3]).getByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[5]).getByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -192,7 +165,6 @@ test('On selection change, send request and update checked value', async () => {
|
||||||
global.featureFlags = {
|
global.featureFlags = {
|
||||||
[FeatureFlag.HorizontalFilterBar]: true,
|
[FeatureFlag.HorizontalFilterBar]: true,
|
||||||
};
|
};
|
||||||
fetchMock.reset();
|
|
||||||
fetchMock.put('glob:*/api/v1/dashboard/1', {
|
fetchMock.put('glob:*/api/v1/dashboard/1', {
|
||||||
result: {
|
result: {
|
||||||
json_metadata: JSON.stringify({
|
json_metadata: JSON.stringify({
|
||||||
|
|
@ -209,14 +181,14 @@ test('On selection change, send request and update checked value', async () => {
|
||||||
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[2]).getByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[4]).getByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
|
|
||||||
userEvent.click(screen.getByText('Horizontal (Top)'));
|
userEvent.click(screen.getByText('Horizontal (Top)'));
|
||||||
|
|
||||||
// 1st check - checkmark appears immediately after click
|
// 1st check - checkmark appears immediately after click
|
||||||
expect(
|
expect(
|
||||||
await within(screen.getAllByRole('menuitem')[3]).findByLabelText('check'),
|
await within(screen.getAllByRole('menuitem')[5]).findByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
// successful query
|
// successful query
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
|
|
@ -231,18 +203,21 @@ test('On selection change, send request and update checked value', async () => {
|
||||||
);
|
);
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
const menuitems = screen.getAllByRole('menuitem');
|
const menuitems = screen.getAllByRole('menuitem');
|
||||||
expect(menuitems.length).toBeGreaterThanOrEqual(3);
|
expect(menuitems.length).toBeGreaterThanOrEqual(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
userEvent.click(screen.getByLabelText('gear'));
|
||||||
|
userEvent.hover(screen.getByText('Orientation of filter bar'));
|
||||||
|
expect(await screen.findByText('Vertical (Left)')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
||||||
|
|
||||||
// 2nd check - checkmark stays after successful query
|
// 2nd check - checkmark stays after successful query
|
||||||
expect(
|
expect(
|
||||||
await within(screen.getAllByRole('menuitem')[3]).findByLabelText('check'),
|
await within(screen.getAllByRole('menuitem')[5]).findByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[2]).queryByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[4]).queryByLabelText('check'),
|
||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
|
|
||||||
fetchMock.reset();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('On failed request, restore previous selection', async () => {
|
test('On failed request, restore previous selection', async () => {
|
||||||
|
|
@ -250,7 +225,6 @@ test('On failed request, restore previous selection', async () => {
|
||||||
global.featureFlags = {
|
global.featureFlags = {
|
||||||
[FeatureFlag.HorizontalFilterBar]: true,
|
[FeatureFlag.HorizontalFilterBar]: true,
|
||||||
};
|
};
|
||||||
fetchMock.reset();
|
|
||||||
fetchMock.put('glob:*/api/v1/dashboard/1', 400);
|
fetchMock.put('glob:*/api/v1/dashboard/1', 400);
|
||||||
|
|
||||||
const dangerToastSpy = jest.spyOn(mockedMessageActions, 'addDangerToast');
|
const dangerToastSpy = jest.spyOn(mockedMessageActions, 'addDangerToast');
|
||||||
|
|
@ -263,10 +237,10 @@ test('On failed request, restore previous selection', async () => {
|
||||||
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
expect(screen.getByText('Horizontal (Top)')).toBeInTheDocument();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[2]).getByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[4]).getByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[3]).queryByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[5]).queryByLabelText('check'),
|
||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
|
|
||||||
userEvent.click(await screen.findByText('Horizontal (Top)'));
|
userEvent.click(await screen.findByText('Horizontal (Top)'));
|
||||||
|
|
@ -284,16 +258,14 @@ test('On failed request, restore previous selection', async () => {
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
const menuitems = screen.getAllByRole('menuitem');
|
const menuitems = screen.getAllByRole('menuitem');
|
||||||
expect(menuitems.length).toBeGreaterThanOrEqual(3);
|
expect(menuitems.length).toBeGreaterThanOrEqual(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
// checkmark gets rolled back to the original selection after successful query
|
// checkmark gets rolled back to the original selection after successful query
|
||||||
expect(
|
expect(
|
||||||
await within(screen.getAllByRole('menuitem')[2]).findByLabelText('check'),
|
await within(screen.getAllByRole('menuitem')[4]).findByLabelText('check'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
within(screen.getAllByRole('menuitem')[3]).queryByLabelText('check'),
|
within(screen.getAllByRole('menuitem')[5]).queryByLabelText('check'),
|
||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
|
|
||||||
fetchMock.reset();
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -83,13 +83,9 @@ const FilterBarSettings = () => {
|
||||||
);
|
);
|
||||||
const [selectedFilterBarOrientation, setSelectedFilterBarOrientation] =
|
const [selectedFilterBarOrientation, setSelectedFilterBarOrientation] =
|
||||||
useState(filterBarOrientation);
|
useState(filterBarOrientation);
|
||||||
const isCrossFiltersFeatureEnabled = isFeatureEnabled(
|
|
||||||
FeatureFlag.DashboardCrossFilters,
|
|
||||||
);
|
|
||||||
const shouldEnableCrossFilters =
|
|
||||||
isCrossFiltersEnabled && isCrossFiltersFeatureEnabled;
|
|
||||||
const [crossFiltersEnabled, setCrossFiltersEnabled] = useState<boolean>(
|
const [crossFiltersEnabled, setCrossFiltersEnabled] = useState<boolean>(
|
||||||
shouldEnableCrossFilters,
|
isCrossFiltersEnabled,
|
||||||
);
|
);
|
||||||
const canEdit = useSelector<RootState, boolean>(
|
const canEdit = useSelector<RootState, boolean>(
|
||||||
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
|
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
|
||||||
|
|
@ -188,7 +184,7 @@ const FilterBarSettings = () => {
|
||||||
divider: canSetHorizontalFilterBar,
|
divider: canSetHorizontalFilterBar,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (isCrossFiltersFeatureEnabled && canEdit) {
|
if (canEdit) {
|
||||||
items.push({
|
items.push({
|
||||||
key: CROSS_FILTERS_MENU_KEY,
|
key: CROSS_FILTERS_MENU_KEY,
|
||||||
label: crossFiltersMenuItem,
|
label: crossFiltersMenuItem,
|
||||||
|
|
@ -222,7 +218,6 @@ const FilterBarSettings = () => {
|
||||||
crossFiltersMenuItem,
|
crossFiltersMenuItem,
|
||||||
dashboardId,
|
dashboardId,
|
||||||
filterValues,
|
filterValues,
|
||||||
isCrossFiltersFeatureEnabled,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!menuItems.length) {
|
if (!menuItems.length) {
|
||||||
|
|
|
||||||
|
|
@ -62,15 +62,12 @@ import crossFiltersSelector from '../CrossFilters/selectors';
|
||||||
import CrossFilter from '../CrossFilters/CrossFilter';
|
import CrossFilter from '../CrossFilters/CrossFilter';
|
||||||
import { useFilterOutlined } from '../useFilterOutlined';
|
import { useFilterOutlined } from '../useFilterOutlined';
|
||||||
import { useChartsVerboseMaps } from '../utils';
|
import { useChartsVerboseMaps } from '../utils';
|
||||||
import { CrossFilterIndicator } from '../../selectors';
|
|
||||||
|
|
||||||
type FilterControlsProps = {
|
type FilterControlsProps = {
|
||||||
dataMaskSelected: DataMaskStateWithId;
|
dataMaskSelected: DataMaskStateWithId;
|
||||||
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
|
onFilterSelectionChange: (filter: Filter, dataMask: DataMask) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EMPTY_ARRAY: CrossFilterIndicator[] = [];
|
|
||||||
|
|
||||||
const FilterControls: FC<FilterControlsProps> = ({
|
const FilterControls: FC<FilterControlsProps> = ({
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
onFilterSelectionChange,
|
onFilterSelectionChange,
|
||||||
|
|
@ -94,20 +91,15 @@ const FilterControls: FC<FilterControlsProps> = ({
|
||||||
const chartLayoutItems = useChartLayoutItems();
|
const chartLayoutItems = useChartLayoutItems();
|
||||||
const verboseMaps = useChartsVerboseMaps();
|
const verboseMaps = useChartsVerboseMaps();
|
||||||
|
|
||||||
const isCrossFiltersEnabled = isFeatureEnabled(
|
|
||||||
FeatureFlag.DashboardCrossFilters,
|
|
||||||
);
|
|
||||||
const selectedCrossFilters = useMemo(
|
const selectedCrossFilters = useMemo(
|
||||||
() =>
|
() =>
|
||||||
isCrossFiltersEnabled
|
crossFiltersSelector({
|
||||||
? crossFiltersSelector({
|
|
||||||
dataMask,
|
dataMask,
|
||||||
chartIds,
|
chartIds,
|
||||||
chartLayoutItems,
|
chartLayoutItems,
|
||||||
verboseMaps,
|
verboseMaps,
|
||||||
})
|
}),
|
||||||
: EMPTY_ARRAY,
|
[chartIds, chartLayoutItems, dataMask, verboseMaps],
|
||||||
[chartIds, chartLayoutItems, dataMask, isCrossFiltersEnabled, verboseMaps],
|
|
||||||
);
|
);
|
||||||
const { filterControlFactory, filtersWithValues } = useFilterControlFactory(
|
const { filterControlFactory, filtersWithValues } = useFilterControlFactory(
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FC, memo, useMemo } from 'react';
|
import { FC, memo, useMemo } from 'react';
|
||||||
import {
|
import { DataMaskStateWithId, styled, t } from '@superset-ui/core';
|
||||||
DataMaskStateWithId,
|
|
||||||
FeatureFlag,
|
|
||||||
isFeatureEnabled,
|
|
||||||
styled,
|
|
||||||
t,
|
|
||||||
} from '@superset-ui/core';
|
|
||||||
import Loading from 'src/components/Loading';
|
import Loading from 'src/components/Loading';
|
||||||
import { RootState } from 'src/dashboard/types';
|
import { RootState } from 'src/dashboard/types';
|
||||||
import { useChartLayoutItems } from 'src/dashboard/util/useChartLayoutItems';
|
import { useChartLayoutItems } from 'src/dashboard/util/useChartLayoutItems';
|
||||||
|
|
@ -35,7 +29,6 @@ import { useChartsVerboseMaps, getFilterBarTestId } from './utils';
|
||||||
import { HorizontalBarProps } from './types';
|
import { HorizontalBarProps } from './types';
|
||||||
import FilterBarSettings from './FilterBarSettings';
|
import FilterBarSettings from './FilterBarSettings';
|
||||||
import crossFiltersSelector from './CrossFilters/selectors';
|
import crossFiltersSelector from './CrossFilters/selectors';
|
||||||
import { CrossFilterIndicator } from '../selectors';
|
|
||||||
|
|
||||||
const HorizontalBar = styled.div`
|
const HorizontalBar = styled.div`
|
||||||
${({ theme }) => `
|
${({ theme }) => `
|
||||||
|
|
@ -72,7 +65,6 @@ const FilterBarEmptyStateContainer = styled.div`
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EMPTY_ARRAY: CrossFilterIndicator[] = [];
|
|
||||||
const HorizontalFilterBar: FC<HorizontalBarProps> = ({
|
const HorizontalFilterBar: FC<HorizontalBarProps> = ({
|
||||||
actions,
|
actions,
|
||||||
dataMaskSelected,
|
dataMaskSelected,
|
||||||
|
|
@ -85,22 +77,17 @@ const HorizontalFilterBar: FC<HorizontalBarProps> = ({
|
||||||
);
|
);
|
||||||
const chartIds = useChartIds();
|
const chartIds = useChartIds();
|
||||||
const chartLayoutItems = useChartLayoutItems();
|
const chartLayoutItems = useChartLayoutItems();
|
||||||
const isCrossFiltersEnabled = isFeatureEnabled(
|
|
||||||
FeatureFlag.DashboardCrossFilters,
|
|
||||||
);
|
|
||||||
const verboseMaps = useChartsVerboseMaps();
|
const verboseMaps = useChartsVerboseMaps();
|
||||||
|
|
||||||
const selectedCrossFilters = useMemo(
|
const selectedCrossFilters = useMemo(
|
||||||
() =>
|
() =>
|
||||||
isCrossFiltersEnabled
|
crossFiltersSelector({
|
||||||
? crossFiltersSelector({
|
|
||||||
dataMask,
|
dataMask,
|
||||||
chartIds,
|
chartIds,
|
||||||
chartLayoutItems,
|
chartLayoutItems,
|
||||||
verboseMaps,
|
verboseMaps,
|
||||||
})
|
}),
|
||||||
: EMPTY_ARRAY,
|
[chartIds, chartLayoutItems, dataMask, verboseMaps],
|
||||||
[chartIds, chartLayoutItems, dataMask, isCrossFiltersEnabled, verboseMaps],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasFilters = filterValues.length > 0 || selectedCrossFilters.length > 0;
|
const hasFilters = filterValues.length > 0 || selectedCrossFilters.length > 0;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ const renderWrapper = (overrideProps?: Record<string, any>) =>
|
||||||
render(<HorizontalBar {...defaultProps} {...overrideProps} />, {
|
render(<HorizontalBar {...defaultProps} {...overrideProps} />, {
|
||||||
useRedux: true,
|
useRedux: true,
|
||||||
initialState: {
|
initialState: {
|
||||||
|
dashboardState: {
|
||||||
|
sliceIds: [],
|
||||||
|
},
|
||||||
dashboardInfo: {
|
dashboardInfo: {
|
||||||
dash_edit_perm: true,
|
dash_edit_perm: true,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import {
|
||||||
FC,
|
FC,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { FeatureFlag, isFeatureEnabled, styled, t } from '@superset-ui/core';
|
import { styled, t } from '@superset-ui/core';
|
||||||
import Icons from 'src/components/Icons';
|
import Icons from 'src/components/Icons';
|
||||||
import Loading from 'src/components/Loading';
|
import Loading from 'src/components/Loading';
|
||||||
import { EmptyState } from 'src/components/EmptyState';
|
import { EmptyState } from 'src/components/EmptyState';
|
||||||
|
|
@ -191,14 +191,6 @@ const VerticalFilterBar: FC<VerticalBarProps> = ({
|
||||||
[canEdit, dataMaskSelected, filterValues.length, onSelectionChange],
|
[canEdit, dataMaskSelected, filterValues.length, onSelectionChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const crossFilters = useMemo(
|
|
||||||
() =>
|
|
||||||
isFeatureEnabled(FeatureFlag.DashboardCrossFilters) ? (
|
|
||||||
<CrossFiltersVertical />
|
|
||||||
) : null,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterBarScrollContext.Provider value={isScrolling}>
|
<FilterBarScrollContext.Provider value={isScrolling}>
|
||||||
<BarWrapper
|
<BarWrapper
|
||||||
|
|
@ -231,7 +223,7 @@ const VerticalFilterBar: FC<VerticalBarProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<div css={tabPaneStyle} onScroll={onScroll}>
|
<div css={tabPaneStyle} onScroll={onScroll}>
|
||||||
<>
|
<>
|
||||||
{crossFilters}
|
<CrossFiltersVertical />
|
||||||
{filterControls}
|
{filterControls}
|
||||||
</>
|
</>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,9 @@ import {
|
||||||
DataMaskStateWithId,
|
DataMaskStateWithId,
|
||||||
DataMaskType,
|
DataMaskType,
|
||||||
ensureIsArray,
|
ensureIsArray,
|
||||||
FeatureFlag,
|
|
||||||
Filters,
|
Filters,
|
||||||
FilterState,
|
FilterState,
|
||||||
getColumnLabel,
|
getColumnLabel,
|
||||||
isFeatureEnabled,
|
|
||||||
NativeFilterType,
|
NativeFilterType,
|
||||||
NO_TIME_RANGE,
|
NO_TIME_RANGE,
|
||||||
QueryFormColumn,
|
QueryFormColumn,
|
||||||
|
|
@ -289,7 +287,6 @@ export const selectChartCrossFilters = (
|
||||||
filterEmitter = false,
|
filterEmitter = false,
|
||||||
): Indicator[] | CrossFilterIndicator[] => {
|
): Indicator[] | CrossFilterIndicator[] => {
|
||||||
let crossFilterIndicators: any = [];
|
let crossFilterIndicators: any = [];
|
||||||
if (isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
crossFilterIndicators = Object.values(chartConfiguration)
|
crossFilterIndicators = Object.values(chartConfiguration)
|
||||||
.filter(chartConfig => {
|
.filter(chartConfig => {
|
||||||
const inScope =
|
const inScope =
|
||||||
|
|
@ -321,7 +318,6 @@ export const selectChartCrossFilters = (
|
||||||
return { ...filterIndicator, status: filterStatus };
|
return { ...filterIndicator, status: filterStatus };
|
||||||
})
|
})
|
||||||
.filter(filter => filter.status === IndicatorStatus.CrossFilterApplied);
|
.filter(filter => filter.status === IndicatorStatus.CrossFilterApplied);
|
||||||
}
|
|
||||||
|
|
||||||
return crossFilterIndicators;
|
return crossFilterIndicators;
|
||||||
};
|
};
|
||||||
|
|
@ -379,7 +375,6 @@ export const selectNativeIndicatorsForChart = (
|
||||||
});
|
});
|
||||||
|
|
||||||
let crossFilterIndicators: any = [];
|
let crossFilterIndicators: any = [];
|
||||||
if (isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
crossFilterIndicators = selectChartCrossFilters(
|
crossFilterIndicators = selectChartCrossFilters(
|
||||||
dataMask,
|
dataMask,
|
||||||
chartId,
|
chartId,
|
||||||
|
|
@ -388,7 +383,6 @@ export const selectNativeIndicatorsForChart = (
|
||||||
appliedColumns,
|
appliedColumns,
|
||||||
rejectedColumns,
|
rejectedColumns,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
const indicators = crossFilterIndicators.concat(nativeFilterIndicators);
|
const indicators = crossFilterIndicators.concat(nativeFilterIndicators);
|
||||||
cachedNativeIndicatorsForChart[chartId] = indicators;
|
cachedNativeIndicatorsForChart[chartId] = indicators;
|
||||||
cachedNativeFilterDataForChart[chartId] = {
|
cachedNativeFilterDataForChart[chartId] = {
|
||||||
|
|
|
||||||
|
|
@ -16,58 +16,12 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { Behavior, FeatureFlag, isFeatureEnabled } from '@superset-ui/core';
|
import { Behavior } from '@superset-ui/core';
|
||||||
import { DashboardLayout } from 'src/dashboard/types';
|
import { DashboardLayout } from 'src/dashboard/types';
|
||||||
import { CHART_TYPE } from 'src/dashboard/util/componentTypes';
|
import { CHART_TYPE } from 'src/dashboard/util/componentTypes';
|
||||||
import { nativeFilterGate, findTabsWithChartsInScope } from './utils';
|
import { nativeFilterGate, findTabsWithChartsInScope } from './utils';
|
||||||
|
|
||||||
jest.mock('@superset-ui/core', () => ({
|
|
||||||
...jest.requireActual('@superset-ui/core'),
|
|
||||||
isFeatureEnabled: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const mockedIsFeatureEnabled = isFeatureEnabled as jest.Mock;
|
|
||||||
|
|
||||||
describe('nativeFilterGate', () => {
|
describe('nativeFilterGate', () => {
|
||||||
describe('with all feature flags disabled', () => {
|
|
||||||
beforeAll(() => {
|
|
||||||
mockedIsFeatureEnabled.mockImplementation(() => false);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
mockedIsFeatureEnabled.mockRestore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true for regular chart', () => {
|
|
||||||
expect(nativeFilterGate([])).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true for cross filter chart', () => {
|
|
||||||
expect(nativeFilterGate([Behavior.InteractiveChart])).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false for native filter chart with cross filter support', () => {
|
|
||||||
expect(
|
|
||||||
nativeFilterGate([Behavior.NativeFilter, Behavior.InteractiveChart]),
|
|
||||||
).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false for native filter behavior', () => {
|
|
||||||
expect(nativeFilterGate([Behavior.NativeFilter])).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('with cross filters and experimental feature flag enabled', () => {
|
|
||||||
beforeAll(() => {
|
|
||||||
mockedIsFeatureEnabled.mockImplementation((featureFlag: FeatureFlag) =>
|
|
||||||
[FeatureFlag.DashboardCrossFilters].includes(featureFlag),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
mockedIsFeatureEnabled.mockRestore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true for regular chart', () => {
|
it('should return true for regular chart', () => {
|
||||||
expect(nativeFilterGate([])).toEqual(true);
|
expect(nativeFilterGate([])).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
@ -86,7 +40,6 @@ describe('nativeFilterGate', () => {
|
||||||
expect(nativeFilterGate([Behavior.NativeFilter])).toEqual(false);
|
expect(nativeFilterGate([Behavior.NativeFilter])).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
test('findTabsWithChartsInScope should handle a recursive layout structure', () => {
|
test('findTabsWithChartsInScope should handle a recursive layout structure', () => {
|
||||||
const dashboardLayout = {
|
const dashboardLayout = {
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ import {
|
||||||
EXTRA_FORM_DATA_APPEND_KEYS,
|
EXTRA_FORM_DATA_APPEND_KEYS,
|
||||||
EXTRA_FORM_DATA_OVERRIDE_KEYS,
|
EXTRA_FORM_DATA_OVERRIDE_KEYS,
|
||||||
ExtraFormData,
|
ExtraFormData,
|
||||||
isFeatureEnabled,
|
|
||||||
FeatureFlag,
|
|
||||||
Filter,
|
Filter,
|
||||||
getChartMetadataRegistry,
|
getChartMetadataRegistry,
|
||||||
QueryFormData,
|
QueryFormData,
|
||||||
|
|
@ -150,8 +148,7 @@ export function getExtraFormData(
|
||||||
export function nativeFilterGate(behaviors: Behavior[]): boolean {
|
export function nativeFilterGate(behaviors: Behavior[]): boolean {
|
||||||
return (
|
return (
|
||||||
!behaviors.includes(Behavior.NativeFilter) ||
|
!behaviors.includes(Behavior.NativeFilter) ||
|
||||||
(isFeatureEnabled(FeatureFlag.DashboardCrossFilters) &&
|
behaviors.includes(Behavior.InteractiveChart)
|
||||||
behaviors.includes(Behavior.InteractiveChart))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { Behavior, getChartMetadataRegistry, VizType } from '@superset-ui/core';
|
||||||
Behavior,
|
|
||||||
FeatureFlag,
|
|
||||||
getChartMetadataRegistry,
|
|
||||||
VizType,
|
|
||||||
} from '@superset-ui/core';
|
|
||||||
import { getCrossFiltersConfiguration } from './crossFilters';
|
import { getCrossFiltersConfiguration } from './crossFilters';
|
||||||
import { DEFAULT_CROSS_FILTER_SCOPING } from '../constants';
|
import { DEFAULT_CROSS_FILTER_SCOPING } from '../constants';
|
||||||
|
|
||||||
|
|
@ -152,11 +147,6 @@ afterEach(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Generate correct cross filters configuration without initial configuration', () => {
|
test('Generate correct cross filters configuration without initial configuration', () => {
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
expect(getCrossFiltersConfiguration(DASHBOARD_LAYOUT, {}, CHARTS)).toEqual({
|
expect(getCrossFiltersConfiguration(DASHBOARD_LAYOUT, {}, CHARTS)).toEqual({
|
||||||
chartConfiguration: {
|
chartConfiguration: {
|
||||||
|
|
@ -186,11 +176,6 @@ test('Generate correct cross filters configuration without initial configuration
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Generate correct cross filters configuration with initial configuration', () => {
|
test('Generate correct cross filters configuration with initial configuration', () => {
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
getCrossFiltersConfiguration(
|
getCrossFiltersConfiguration(
|
||||||
DASHBOARD_LAYOUT,
|
DASHBOARD_LAYOUT,
|
||||||
|
|
@ -227,25 +212,7 @@ test('Generate correct cross filters configuration with initial configuration',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Return undefined if DASHBOARD_CROSS_FILTERS feature flag is disabled', () => {
|
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: false,
|
|
||||||
};
|
|
||||||
expect(
|
|
||||||
getCrossFiltersConfiguration(
|
|
||||||
DASHBOARD_LAYOUT,
|
|
||||||
CHART_CONFIG_METADATA,
|
|
||||||
CHARTS,
|
|
||||||
),
|
|
||||||
).toEqual(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Recalculate charts in global filter scope when charts change', () => {
|
test('Recalculate charts in global filter scope when charts change', () => {
|
||||||
// @ts-ignore
|
|
||||||
global.featureFlags = {
|
|
||||||
[FeatureFlag.DashboardCrossFilters]: true,
|
|
||||||
};
|
|
||||||
expect(
|
expect(
|
||||||
getCrossFiltersConfiguration(
|
getCrossFiltersConfiguration(
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,8 @@
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import {
|
import {
|
||||||
Behavior,
|
Behavior,
|
||||||
FeatureFlag,
|
|
||||||
getChartMetadataRegistry,
|
getChartMetadataRegistry,
|
||||||
isDefined,
|
isDefined,
|
||||||
isFeatureEnabled,
|
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { getChartIdsInFilterScope } from './getChartIdsInFilterScope';
|
import { getChartIdsInFilterScope } from './getChartIdsInFilterScope';
|
||||||
import {
|
import {
|
||||||
|
|
@ -38,8 +36,7 @@ import { CHART_TYPE } from './componentTypes';
|
||||||
export const isCrossFiltersEnabled = (
|
export const isCrossFiltersEnabled = (
|
||||||
metadataCrossFiltersEnabled: boolean | undefined,
|
metadataCrossFiltersEnabled: boolean | undefined,
|
||||||
): boolean =>
|
): boolean =>
|
||||||
isFeatureEnabled(FeatureFlag.DashboardCrossFilters) &&
|
metadataCrossFiltersEnabled === undefined || metadataCrossFiltersEnabled;
|
||||||
(metadataCrossFiltersEnabled === undefined || metadataCrossFiltersEnabled);
|
|
||||||
|
|
||||||
export const getCrossFiltersConfiguration = (
|
export const getCrossFiltersConfiguration = (
|
||||||
dashboardLayout: DashboardLayout,
|
dashboardLayout: DashboardLayout,
|
||||||
|
|
@ -49,10 +46,6 @@ export const getCrossFiltersConfiguration = (
|
||||||
>,
|
>,
|
||||||
charts: ChartsState,
|
charts: ChartsState,
|
||||||
) => {
|
) => {
|
||||||
if (!isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const chartLayoutItems = Object.values(dashboardLayout).filter(
|
const chartLayoutItems = Object.values(dashboardLayout).filter(
|
||||||
item => item?.type === CHART_TYPE,
|
item => item?.type === CHART_TYPE,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ import {
|
||||||
DataMask,
|
DataMask,
|
||||||
DataMaskStateWithId,
|
DataMaskStateWithId,
|
||||||
DataMaskWithId,
|
DataMaskWithId,
|
||||||
isFeatureEnabled,
|
|
||||||
FeatureFlag,
|
|
||||||
Filter,
|
Filter,
|
||||||
FilterConfiguration,
|
FilterConfiguration,
|
||||||
Filters,
|
Filters,
|
||||||
|
|
@ -148,7 +146,6 @@ const dataMaskReducer = produce(
|
||||||
// TODO: update hydrate to .ts
|
// TODO: update hydrate to .ts
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
case HYDRATE_DASHBOARD:
|
case HYDRATE_DASHBOARD:
|
||||||
if (isFeatureEnabled(FeatureFlag.DashboardCrossFilters)) {
|
|
||||||
Object.keys(
|
Object.keys(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
action.data.dashboardInfo?.metadata?.chart_configuration,
|
action.data.dashboardInfo?.metadata?.chart_configuration,
|
||||||
|
|
@ -157,7 +154,6 @@ const dataMaskReducer = produce(
|
||||||
...getInitialDataMask(id), // take initial data
|
...getInitialDataMask(id), // take initial data
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
|
||||||
fillNativeFilters(
|
fillNativeFilters(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
action.data.dashboardInfo?.metadata?.native_filter_configuration ??
|
action.data.dashboardInfo?.metadata?.native_filter_configuration ??
|
||||||
|
|
|
||||||
|
|
@ -314,15 +314,12 @@ const databaseFixture: DatabaseObject = {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('DatabaseModal', () => {
|
describe('DatabaseModal', () => {
|
||||||
const renderAndWait = async () => {
|
const renderAndWait = async () =>
|
||||||
const mounted = act(async () => {
|
waitFor(() =>
|
||||||
render(<DatabaseModal {...dbProps} />, {
|
render(<DatabaseModal {...dbProps} />, {
|
||||||
useRedux: true,
|
useRedux: true,
|
||||||
});
|
}),
|
||||||
});
|
);
|
||||||
|
|
||||||
return mounted;
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await renderAndWait();
|
await renderAndWait();
|
||||||
|
|
|
||||||
|
|
@ -487,7 +487,6 @@ DEFAULT_FEATURE_FLAGS: dict[str, bool] = {
|
||||||
"LISTVIEWS_DEFAULT_CARD_VIEW": False,
|
"LISTVIEWS_DEFAULT_CARD_VIEW": False,
|
||||||
# When True, this escapes HTML (rather than rendering it) in Markdown components
|
# When True, this escapes HTML (rather than rendering it) in Markdown components
|
||||||
"ESCAPE_MARKDOWN_HTML": False,
|
"ESCAPE_MARKDOWN_HTML": False,
|
||||||
"DASHBOARD_CROSS_FILTERS": True, # deprecated
|
|
||||||
"DASHBOARD_VIRTUALIZATION": True,
|
"DASHBOARD_VIRTUALIZATION": True,
|
||||||
# This feature flag is stil in beta and is not recommended for production use.
|
# This feature flag is stil in beta and is not recommended for production use.
|
||||||
"GLOBAL_ASYNC_QUERIES": False,
|
"GLOBAL_ASYNC_QUERIES": False,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue