Skip to content

Commit ddc7f12

Browse files
michael-s-molinaPawankumarES
authored andcommitted
fix: Prevents last temporal filter removal (apache#22982)
1 parent 99303a6 commit ddc7f12

File tree

3 files changed

+41
-69
lines changed

3 files changed

+41
-69
lines changed

superset-frontend/src/explore/components/ControlPanelsContainer.tsx

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
CustomControlItem,
4747
Dataset,
4848
ExpandedControlItem,
49+
isTemporalColumn,
4950
sections,
5051
} from '@superset-ui/chart-controls';
5152
import { useSelector } from 'react-redux';
@@ -293,13 +294,17 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
293294
const previousXAxis = usePrevious(x_axis);
294295

295296
useEffect(() => {
296-
if (x_axis && x_axis !== previousXAxis) {
297+
if (
298+
x_axis &&
299+
x_axis !== previousXAxis &&
300+
isTemporalColumn(x_axis, props.exploreState.datasource)
301+
) {
297302
const noFilter =
298303
!adhoc_filters ||
299304
!adhoc_filters.find(
300305
filter =>
301306
filter.expressionType === 'SIMPLE' &&
302-
filter.operator === 'TEMPORAL_RANGE' &&
307+
filter.operator === Operators.TEMPORAL_RANGE &&
303308
filter.subject === x_axis,
304309
);
305310
if (noFilter) {
@@ -314,7 +319,7 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
314319
{
315320
clause: 'WHERE',
316321
subject: x_axis,
317-
operator: 'TEMPORAL_RANGE',
322+
operator: Operators.TEMPORAL_RANGE,
318323
comparator: defaultTimeFilter || NO_TIME_RANGE,
319324
expressionType: 'SIMPLE',
320325
},
@@ -329,6 +334,7 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
329334
setControlValue,
330335
defaultTimeFilter,
331336
previousXAxis,
337+
props.exploreState.datasource,
332338
]);
333339

334340
useEffect(() => {
@@ -482,28 +488,21 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
482488
: baseDescription;
483489

484490
if (name === 'adhoc_filters') {
485-
restProps.confirmDeletion = {
486-
triggerCondition: (
487-
valueToBeDeleted: Record<string, any>,
488-
values: Record<string, any>[],
489-
) => {
490-
const isTemporalRange = (filter: Record<string, any>) =>
491-
filter.operator === Operators.TEMPORAL_RANGE;
492-
if (isTemporalRange(valueToBeDeleted)) {
493-
const count = values.filter(isTemporalRange).length;
494-
if (count < 2) {
495-
return true;
496-
}
491+
restProps.canDelete = (
492+
valueToBeDeleted: Record<string, any>,
493+
values: Record<string, any>[],
494+
) => {
495+
const isTemporalRange = (filter: Record<string, any>) =>
496+
filter.operator === Operators.TEMPORAL_RANGE;
497+
if (isTemporalRange(valueToBeDeleted)) {
498+
const count = values.filter(isTemporalRange).length;
499+
if (count === 1) {
500+
return t(
501+
`You cannot delete the last temporal filter as it's used for time range filters in dashboards.`,
502+
);
497503
}
498-
return false;
499-
},
500-
confirmationTitle: t(
501-
'Are you sure you want to remove the last temporal filter?',
502-
),
503-
confirmationText: t(
504-
`This filter is the last temporal filter. If you proceed,
505-
this chart won't be affected by time range filters in dashboards.`,
506-
),
504+
}
505+
return true;
507506
};
508507
}
509508

superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.tsx

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import AdhocFilterControl from '../FilterControl/AdhocFilterControl';
5959
import DndAdhocFilterOption from './DndAdhocFilterOption';
6060
import { useDefaultTimeFilter } from '../DateFilterControl/utils';
6161

62-
const { confirm } = Modal;
62+
const { warning } = Modal;
6363

6464
const EMPTY_OBJECT = {};
6565
const DND_ACCEPTED_TYPES = [
@@ -78,22 +78,18 @@ export interface DndFilterSelectProps
7878
savedMetrics: Metric[];
7979
selectedMetrics: QueryFormMetric[];
8080
datasource: Datasource;
81-
confirmDeletion?: {
82-
triggerCondition: (
83-
valueToBeDeleted: OptionValueType,
84-
values: OptionValueType[],
85-
) => boolean;
86-
confirmationTitle: string;
87-
confirmationText: string;
88-
};
81+
canDelete?: (
82+
valueToBeDeleted: OptionValueType,
83+
values: OptionValueType[],
84+
) => true | string;
8985
}
9086

9187
const DndFilterSelect = (props: DndFilterSelectProps) => {
9288
const {
9389
datasource,
9490
onChange = () => {},
9591
name: controlName,
96-
confirmDeletion,
92+
canDelete,
9793
} = props;
9894

9995
const propsValues = Array.from(props.value ?? []);
@@ -217,23 +213,14 @@ const DndFilterSelect = (props: DndFilterSelectProps) => {
217213

218214
const onClickClose = useCallback(
219215
(index: number) => {
220-
if (confirmDeletion) {
221-
const { confirmationText, confirmationTitle, triggerCondition } =
222-
confirmDeletion;
223-
if (triggerCondition(values[index], values)) {
224-
confirm({
225-
title: confirmationTitle,
226-
content: confirmationText,
227-
onOk() {
228-
removeValue(index);
229-
},
230-
});
231-
return;
232-
}
216+
const result = canDelete?.(values[index], values);
217+
if (typeof result === 'string') {
218+
warning({ title: t('Warning'), content: result });
219+
return;
233220
}
234221
removeValue(index);
235222
},
236-
[confirmDeletion, removeValue, values],
223+
[canDelete, removeValue, values],
237224
);
238225

239226
const onShiftOptions = useCallback(

superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterControl/index.jsx

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import AdhocFilter, {
5252
import adhocFilterType from 'src/explore/components/controls/FilterControl/adhocFilterType';
5353
import columnType from 'src/explore/components/controls/FilterControl/columnType';
5454

55-
const { confirm } = Modal;
55+
const { warning } = Modal;
5656

5757
const selectedMetricType = PropTypes.oneOfType([
5858
PropTypes.string,
@@ -74,11 +74,7 @@ const propTypes = {
7474
PropTypes.arrayOf(selectedMetricType),
7575
]),
7676
isLoading: PropTypes.bool,
77-
confirmDeletion: PropTypes.shape({
78-
triggerCondition: PropTypes.func,
79-
confirmationTitle: PropTypes.string,
80-
confirmationText: PropTypes.string,
81-
}),
77+
canDelete: PropTypes.func,
8278
};
8379

8480
const defaultProps = {
@@ -196,22 +192,12 @@ class AdhocFilterControl extends React.Component {
196192
}
197193

198194
onRemoveFilter(index) {
199-
const { confirmDeletion } = this.props;
195+
const { canDelete } = this.props;
200196
const { values } = this.state;
201-
const { removeFilter } = this;
202-
if (confirmDeletion) {
203-
const { confirmationText, confirmationTitle, triggerCondition } =
204-
confirmDeletion;
205-
if (triggerCondition(values[index], values)) {
206-
confirm({
207-
title: confirmationTitle,
208-
content: confirmationText,
209-
onOk() {
210-
removeFilter(index);
211-
},
212-
});
213-
return;
214-
}
197+
const result = canDelete?.(values[index], values);
198+
if (typeof result === 'string') {
199+
warning({ title: t('Warning'), content: result });
200+
return;
215201
}
216202
this.removeFilter(index);
217203
}

0 commit comments

Comments
 (0)