mirror of https://github.com/apache/superset.git
chore: Deprecate DND feature flags (#23981)
This commit is contained in:
parent
7fb8b38cdf
commit
7757b61c22
|
@ -73,8 +73,6 @@ These features flags are **safe for production**. They have been tested and will
|
|||
- DRUID_JOINS
|
||||
- EMBEDDABLE_CHARTS
|
||||
- EMBEDDED_SUPERSET
|
||||
- ENABLE_DND_WITH_CLICK_UX
|
||||
- ENABLE_EXPLORE_DRAG_AND_DROP
|
||||
- ENABLE_TEMPLATE_PROCESSING
|
||||
- ESCAPE_MARKDOWN_HTML
|
||||
- LISTVIEWS_DEFAULT_CARD_VIEW
|
||||
|
@ -95,6 +93,7 @@ These features flags currently default to True and **will be removed in a future
|
|||
- DASHBOARD_NATIVE_FILTERS
|
||||
- DASHBOARD_NATIVE_FILTERS_SET
|
||||
- DISABLE_DATASET_SOURCE_EDIT
|
||||
- ENABLE_EXPLORE_DRAG_AND_DROP
|
||||
- ENABLE_EXPLORE_JSON_CSRF_PROTECTION
|
||||
- GENERIC_CHART_AXES
|
||||
- REMOVE_SLICE_LEVEL_LABEL_COLORS
|
||||
|
|
|
@ -244,8 +244,7 @@ export const dndGranularitySqlaControl: typeof dndSeriesControl = {
|
|||
default: (c: Control) => c.default,
|
||||
clearable: false,
|
||||
canDelete: false,
|
||||
ghostButtonText: t('Drop temporal column here'),
|
||||
clickEnabledGhostButtonText: t('Drop a temporal column here or click'),
|
||||
ghostButtonText: t('Drop a temporal column here or click'),
|
||||
optionRenderer: (c: ColumnMeta) => <ColumnOption showType column={c} />,
|
||||
valueRenderer: (c: ColumnMeta) => <ColumnOption column={c} />,
|
||||
valueKey: 'column_name',
|
||||
|
|
|
@ -40,7 +40,6 @@ export enum FeatureFlag {
|
|||
EMBEDDABLE_CHARTS = 'EMBEDDABLE_CHARTS',
|
||||
EMBEDDED_SUPERSET = 'EMBEDDED_SUPERSET',
|
||||
ENABLE_ADVANCED_DATA_TYPES = 'ENABLE_ADVANCED_DATA_TYPES',
|
||||
ENABLE_DND_WITH_CLICK_UX = 'ENABLE_DND_WITH_CLICK_UX',
|
||||
ENABLE_EXPLORE_DRAG_AND_DROP = 'ENABLE_EXPLORE_DRAG_AND_DROP',
|
||||
ENABLE_JAVASCRIPT_CONTROLS = 'ENABLE_JAVASCRIPT_CONTROLS',
|
||||
ENABLE_TEMPLATE_PROCESSING = 'ENABLE_TEMPLATE_PROCESSING',
|
||||
|
|
|
@ -45,7 +45,9 @@ test('renders with default props', async () => {
|
|||
useDnd: true,
|
||||
useRedux: true,
|
||||
});
|
||||
expect(await screen.findByText('Drop columns here')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('Drop columns here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders with value', async () => {
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import {
|
||||
AdhocColumn,
|
||||
FeatureFlag,
|
||||
isFeatureEnabled,
|
||||
tn,
|
||||
QueryFormColumn,
|
||||
t,
|
||||
|
@ -54,7 +52,6 @@ function DndColumnSelect(props: DndColumnSelectProps) {
|
|||
onChange,
|
||||
canDelete = true,
|
||||
ghostButtonText,
|
||||
clickEnabledGhostButtonText,
|
||||
name,
|
||||
label,
|
||||
isTemporal,
|
||||
|
@ -108,11 +105,6 @@ function DndColumnSelect(props: DndColumnSelectProps) {
|
|||
[onChange, optionSelector],
|
||||
);
|
||||
|
||||
const clickEnabled = useMemo(
|
||||
() => isFeatureEnabled(FeatureFlag.ENABLE_DND_WITH_CLICK_UX),
|
||||
[],
|
||||
);
|
||||
|
||||
const valuesRenderer = useCallback(
|
||||
() =>
|
||||
optionSelector.values.map((column, idx) => {
|
||||
|
@ -120,7 +112,7 @@ function DndColumnSelect(props: DndColumnSelectProps) {
|
|||
isAdhocColumn(column) && column.datasourceWarning
|
||||
? t('This column might be incompatible with current dataset')
|
||||
: undefined;
|
||||
return clickEnabled ? (
|
||||
return (
|
||||
<ColumnSelectPopoverTrigger
|
||||
key={idx}
|
||||
columns={options}
|
||||
|
@ -147,22 +139,10 @@ function DndColumnSelect(props: DndColumnSelectProps) {
|
|||
withCaret
|
||||
/>
|
||||
</ColumnSelectPopoverTrigger>
|
||||
) : (
|
||||
<OptionWrapper
|
||||
key={idx}
|
||||
index={idx}
|
||||
clickClose={onClickClose}
|
||||
onShiftOptions={onShiftOptions}
|
||||
type={`${DndItemType.ColumnOption}_${name}_${label}`}
|
||||
canDelete={canDelete}
|
||||
column={column}
|
||||
datasourceWarningMessage={datasourceWarningMessage}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
[
|
||||
canDelete,
|
||||
clickEnabled,
|
||||
isTemporal,
|
||||
label,
|
||||
name,
|
||||
|
@ -198,24 +178,16 @@ function DndColumnSelect(props: DndColumnSelectProps) {
|
|||
togglePopover(true);
|
||||
}, [togglePopover]);
|
||||
|
||||
const labelGhostButtonText = useMemo(() => {
|
||||
if (clickEnabled) {
|
||||
return (
|
||||
clickEnabledGhostButtonText ??
|
||||
ghostButtonText ??
|
||||
tn(
|
||||
'Drop a column here or click',
|
||||
'Drop columns here or click',
|
||||
multi ? 2 : 1,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
const labelGhostButtonText = useMemo(
|
||||
() =>
|
||||
ghostButtonText ??
|
||||
tn('Drop column here', 'Drop columns here', multi ? 2 : 1)
|
||||
);
|
||||
}, [clickEnabled, clickEnabledGhostButtonText, ghostButtonText, multi]);
|
||||
tn(
|
||||
'Drop a column here or click',
|
||||
'Drop columns here or click',
|
||||
multi ? 2 : 1,
|
||||
),
|
||||
[ghostButtonText, multi],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -226,7 +198,7 @@ function DndColumnSelect(props: DndColumnSelectProps) {
|
|||
accept={DndItemType.Column}
|
||||
displayGhostButton={multi || optionSelector.values.length === 0}
|
||||
ghostButtonText={labelGhostButtonText}
|
||||
onClickGhostButton={clickEnabled ? openPopover : undefined}
|
||||
onClickGhostButton={openPopover}
|
||||
{...props}
|
||||
/>
|
||||
<ColumnSelectPopoverTrigger
|
||||
|
|
|
@ -93,7 +93,7 @@ function setup({
|
|||
test('renders with default props', async () => {
|
||||
render(setup(), { useDnd: true });
|
||||
expect(
|
||||
await screen.findByText('Drop columns or metrics here'),
|
||||
await screen.findByText('Drop columns/metrics here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -122,7 +122,7 @@ test('renders options with saved metric', async () => {
|
|||
},
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('Drop columns or metrics here'),
|
||||
await screen.findByText('Drop columns/metrics here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -143,7 +143,7 @@ test('renders options with column', async () => {
|
|||
},
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('Drop columns or metrics here'),
|
||||
await screen.findByText('Drop columns/metrics here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -165,6 +165,6 @@ test('renders options with adhoc metric', async () => {
|
|||
},
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('Drop columns or metrics here'),
|
||||
await screen.findByText('Drop columns/metrics here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
|
|
@ -18,9 +18,7 @@
|
|||
*/
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
FeatureFlag,
|
||||
hasGenericChartAxes,
|
||||
isFeatureEnabled,
|
||||
logging,
|
||||
Metric,
|
||||
QueryFormData,
|
||||
|
@ -397,10 +395,6 @@ const DndFilterSelect = (props: DndFilterSelectProps) => {
|
|||
[controlName, togglePopover],
|
||||
);
|
||||
|
||||
const ghostButtonText = isFeatureEnabled(FeatureFlag.ENABLE_DND_WITH_CLICK_UX)
|
||||
? t('Drop columns/metrics here or click')
|
||||
: t('Drop columns or metrics here');
|
||||
|
||||
return (
|
||||
<>
|
||||
<DndSelectLabel
|
||||
|
@ -408,12 +402,8 @@ const DndFilterSelect = (props: DndFilterSelectProps) => {
|
|||
canDrop={canDrop}
|
||||
valuesRenderer={valuesRenderer}
|
||||
accept={DND_ACCEPTED_TYPES}
|
||||
ghostButtonText={ghostButtonText}
|
||||
onClickGhostButton={
|
||||
isFeatureEnabled(FeatureFlag.ENABLE_DND_WITH_CLICK_UX)
|
||||
? handleClickGhostButton
|
||||
: undefined
|
||||
}
|
||||
ghostButtonText={t('Drop columns/metrics here or click')}
|
||||
onClickGhostButton={handleClickGhostButton}
|
||||
{...props}
|
||||
/>
|
||||
<AdhocFilterPopoverTrigger
|
||||
|
|
|
@ -78,12 +78,16 @@ afterAll(() => {
|
|||
|
||||
test('renders with default props', () => {
|
||||
render(<DndMetricSelect {...defaultProps} />, { useDnd: true });
|
||||
expect(screen.getByText('Drop column or metric here')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Drop a column/metric here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders with default props and multi = true', () => {
|
||||
render(<DndMetricSelect {...defaultProps} multi />, { useDnd: true });
|
||||
expect(screen.getByText('Drop columns or metrics here')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Drop columns/metrics here or click'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('render selected metrics correctly', () => {
|
||||
|
@ -159,7 +163,7 @@ test('remove selected custom metric when metric gets removed from dataset for si
|
|||
|
||||
expect(screen.getByText('Metric B')).toBeVisible();
|
||||
expect(
|
||||
screen.queryByText('Drop column or metric here'),
|
||||
screen.queryByText('Drop a column/metric here or click'),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
const newPropsWithRemovedMetric = {
|
||||
|
@ -182,7 +186,7 @@ test('remove selected custom metric when metric gets removed from dataset for si
|
|||
);
|
||||
|
||||
expect(screen.queryByText('Metric B')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('Drop column or metric here')).toBeVisible();
|
||||
expect(screen.getByText('Drop a column/metric here or click')).toBeVisible();
|
||||
});
|
||||
|
||||
test('remove selected adhoc metric when column gets removed from dataset', async () => {
|
||||
|
|
|
@ -20,10 +20,8 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
ensureIsArray,
|
||||
FeatureFlag,
|
||||
GenericDataType,
|
||||
isAdhocMetricSimple,
|
||||
isFeatureEnabled,
|
||||
isSavedMetric,
|
||||
Metric,
|
||||
QueryFormMetric,
|
||||
|
@ -329,17 +327,11 @@ const DndMetricSelect = (props: any) => {
|
|||
return new AdhocMetric({});
|
||||
}, [droppedItem]);
|
||||
|
||||
const ghostButtonText = isFeatureEnabled(FeatureFlag.ENABLE_DND_WITH_CLICK_UX)
|
||||
? tn(
|
||||
'Drop a column/metric here or click',
|
||||
'Drop columns/metrics here or click',
|
||||
multi ? 2 : 1,
|
||||
)
|
||||
: tn(
|
||||
'Drop column or metric here',
|
||||
'Drop columns or metrics here',
|
||||
multi ? 2 : 1,
|
||||
);
|
||||
const ghostButtonText = tn(
|
||||
'Drop a column/metric here or click',
|
||||
'Drop columns/metrics here or click',
|
||||
multi ? 2 : 1,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="metrics-select">
|
||||
|
@ -350,11 +342,7 @@ const DndMetricSelect = (props: any) => {
|
|||
accept={DND_ACCEPTED_TYPES}
|
||||
ghostButtonText={ghostButtonText}
|
||||
displayGhostButton={multi || value.length === 0}
|
||||
onClickGhostButton={
|
||||
isFeatureEnabled(FeatureFlag.ENABLE_DND_WITH_CLICK_UX)
|
||||
? handleClickGhostButton
|
||||
: undefined
|
||||
}
|
||||
onClickGhostButton={handleClickGhostButton}
|
||||
{...props}
|
||||
/>
|
||||
<AdhocMetricPopoverTrigger
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import { DndItemType } from 'src/explore/components/DndItemType';
|
||||
import DndSelectLabel, {
|
||||
|
@ -29,27 +30,35 @@ const defaultProps: DndSelectLabelProps = {
|
|||
onDrop: jest.fn(),
|
||||
canDrop: () => false,
|
||||
valuesRenderer: () => <span />,
|
||||
ghostButtonText: 'Drop columns here or click',
|
||||
onClickGhostButton: jest.fn(),
|
||||
};
|
||||
|
||||
test('renders with default props', async () => {
|
||||
test('renders with default props', () => {
|
||||
render(<DndSelectLabel {...defaultProps} />, { useDnd: true });
|
||||
expect(await screen.findByText('Drop columns here')).toBeInTheDocument();
|
||||
expect(screen.getByText('Drop columns here or click')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders ghost button when empty', async () => {
|
||||
test('renders ghost button when empty', () => {
|
||||
const ghostButtonText = 'Ghost button text';
|
||||
render(
|
||||
<DndSelectLabel {...defaultProps} ghostButtonText={ghostButtonText} />,
|
||||
{ useDnd: true },
|
||||
);
|
||||
expect(await screen.findByText(ghostButtonText)).toBeInTheDocument();
|
||||
expect(screen.getByText(ghostButtonText)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders values', async () => {
|
||||
test('renders values', () => {
|
||||
const values = 'Values';
|
||||
const valuesRenderer = () => <span>{values}</span>;
|
||||
render(<DndSelectLabel {...defaultProps} valuesRenderer={valuesRenderer} />, {
|
||||
useDnd: true,
|
||||
});
|
||||
expect(await screen.findByText(values)).toBeInTheDocument();
|
||||
expect(screen.getByText(values)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Handles ghost button click', () => {
|
||||
render(<DndSelectLabel {...defaultProps} />, { useDnd: true });
|
||||
userEvent.click(screen.getByText('Drop columns here or click'));
|
||||
expect(defaultProps.onClickGhostButton).toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -35,14 +35,14 @@ import { DndItemType } from '../../DndItemType';
|
|||
export type DndSelectLabelProps = {
|
||||
name: string;
|
||||
accept: DndItemType | DndItemType[];
|
||||
ghostButtonText?: string;
|
||||
ghostButtonText: string;
|
||||
onDrop: (item: DatasourcePanelDndItem) => void;
|
||||
canDrop: (item: DatasourcePanelDndItem) => boolean;
|
||||
canDropValue?: (value: DndItemValue) => boolean;
|
||||
onDropValue?: (value: DndItemValue) => void;
|
||||
valuesRenderer: () => ReactNode;
|
||||
displayGhostButton?: boolean;
|
||||
onClickGhostButton?: () => void;
|
||||
onClickGhostButton: () => void;
|
||||
};
|
||||
|
||||
export default function DndSelectLabel({
|
||||
|
@ -80,7 +80,7 @@ export default function DndSelectLabel({
|
|||
onClick={props.onClickGhostButton}
|
||||
>
|
||||
<Icons.PlusSmall iconColor={theme.colors.grayscale.light1} />
|
||||
{t(props.ghostButtonText || 'Drop columns here')}
|
||||
{t(props.ghostButtonText)}
|
||||
</AddControlLabel>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ export type DndControlProps<ValueType extends JsonValue> =
|
|||
multi?: boolean;
|
||||
canDelete?: boolean;
|
||||
ghostButtonText?: string;
|
||||
clickEnabledGhostButtonText?: string;
|
||||
onChange: (value: ValueType | ValueType[] | null | undefined) => void;
|
||||
};
|
||||
|
||||
|
|
|
@ -458,9 +458,8 @@ DEFAULT_FEATURE_FLAGS: Dict[str, bool] = {
|
|||
# Enables Alerts and reports new implementation
|
||||
"ALERT_REPORTS": False,
|
||||
"DASHBOARD_RBAC": False,
|
||||
"ENABLE_EXPLORE_DRAG_AND_DROP": True,
|
||||
"ENABLE_EXPLORE_DRAG_AND_DROP": True, # deprecated
|
||||
"ENABLE_ADVANCED_DATA_TYPES": False,
|
||||
"ENABLE_DND_WITH_CLICK_UX": True,
|
||||
# Enabling ALERTS_ATTACH_REPORTS, the system sends email and slack message
|
||||
# with screenshot and link
|
||||
# Disables ALERTS_ATTACH_REPORTS, the system DOES NOT generate screenshot
|
||||
|
|
Loading…
Reference in New Issue