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: Add single select and inverse selection to numeric range (#16722) #17372

Merged
merged 7 commits into from
Dec 1, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
/* eslint-disable react-hooks/rules-of-hooks */
import {
ColumnMeta,
InfoTooltipWithTrigger,
Expand All @@ -35,7 +36,7 @@ import {
t,
} from '@superset-ui/core';
import { FormInstance } from 'antd/lib/form';
import { isEmpty, isEqual } from 'lodash';
import { isEqual } from 'lodash';
import React, {
forwardRef,
useCallback,
Expand Down Expand Up @@ -73,6 +74,7 @@ import {
Filter,
NativeFilterType,
} from 'src/dashboard/components/nativeFilters/types';
import { SingleValueType } from 'src/filters/components/Range/SingleValueType';
import { getFormData } from 'src/dashboard/components/nativeFilters/utils';
import {
CASCADING_FILTERS,
Expand Down Expand Up @@ -547,6 +549,15 @@ const FiltersConfigForm = (
!!filterToEdit?.adhoc_filters?.length ||
!!filterToEdit?.time_range;

const hasEnableSingleValue =
formFilter?.controlValues?.enableSingleValue !== undefined ||
filterToEdit?.controlValues?.enableSingleValue !== undefined;

let enableSingleValue = filterToEdit?.controlValues?.enableSingleValue;
if (formFilter?.controlValues?.enableSingleMaxValue !== undefined) {
({ enableSingleValue } = formFilter.controlValues);
}

const hasSorting =
typeof formFilter?.controlValues?.sortAscending === 'boolean' ||
typeof filterToEdit?.controlValues?.sortAscending === 'boolean';
Expand All @@ -572,6 +583,17 @@ const FiltersConfigForm = (
forceUpdate();
};

const onEnableSingleValueChanged = (value: SingleValueType | undefined) => {
const previous = form.getFieldValue('filters')?.[filterId].controlValues;
setNativeFilterFieldValues(form, filterId, {
controlValues: {
...previous,
enableSingleValue: value,
},
});
forceUpdate();
};

const validatePreFilter = () =>
setTimeout(
() =>
Expand Down Expand Up @@ -673,12 +695,13 @@ const FiltersConfigForm = (
]);

useEffect(() => {
// Run only once when the control items are available
if (isActive && !isEmpty(controlItems)) {
// Run only once
if (isActive) {
const hasCheckedAdvancedControl =
hasParentFilter ||
hasPreFilter ||
hasSorting ||
hasEnableSingleValue ||
Object.keys(controlItems)
.filter(key => !BASIC_CONTROL_ITEMS.includes(key))
.some(key => controlItems[key].checked);
Expand Down Expand Up @@ -1141,7 +1164,7 @@ const FiltersConfigForm = (
</CollapsibleControl>
</CleanFormItem>
)}
{formFilter?.filterType !== 'filter_range' && (
{formFilter?.filterType !== 'filter_range' ? (
<CleanFormItem name={['filters', filterId, 'sortFilter']}>
<CollapsibleControl
initialValue={hasSorting}
Expand Down Expand Up @@ -1208,6 +1231,48 @@ const FiltersConfigForm = (
)}
</CollapsibleControl>
</CleanFormItem>
) : (
<CleanFormItem name={['filters', filterId, 'rangeFilter']}>
<CollapsibleControl
initialValue={hasEnableSingleValue}
title={t('Single Value')}
onChange={checked => {
onEnableSingleValueChanged(
checked ? SingleValueType.Exact : undefined,
);
formChanged();
}}
>
<StyledRowFormItem
name={[
'filters',
filterId,
'controlValues',
'enableSingleValue',
]}
initialValue={enableSingleValue}
label={
<StyledLabel>{t('Single value type')}</StyledLabel>
}
>
<Radio.Group
onChange={value =>
onEnableSingleValueChanged(value.target.value)
}
>
<Radio value={SingleValueType.Minimum}>
{t('Minimum')}
</Radio>
<Radio value={SingleValueType.Exact}>
{t('Exact')}
</Radio>
<Radio value={SingleValueType.Maximum}>
{t('Maximum')}
</Radio>
</Radio.Group>
</StyledRowFormItem>
</CollapsibleControl>
</CleanFormItem>
)}
</Collapse.Panel>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ test('Should render null empty when "getControlItems" return []', () => {
expect(container.children).toHaveLength(0);
});

test('Should render null empty when "getControlItems" return enableSingleValue', () => {
const props = createProps();
(getControlItems as jest.Mock).mockReturnValue([
{ name: 'enableSingleValue', config: { renderTrigger: true } },
]);
const controlItemsMap = getControlItemsMap(props);
const { container } = renderControlItems(controlItemsMap);
expect(container.children).toHaveLength(0);
});

test('Should render null empty when "controlItems" are falsy', () => {
const props = createProps();
const controlItems = [null, false, {}, { config: { renderTrigger: false } }];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ export default function getControlItemsMap({
.filter(
(controlItem: CustomControlItem) =>
controlItem?.config?.renderTrigger &&
controlItem.name !== 'sortAscending',
controlItem.name !== 'sortAscending' &&
controlItem.name !== 'enableSingleValue',
)
.forEach(controlItem => {
const initialValue =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { AppSection, GenericDataType } from '@superset-ui/core';
import React from 'react';
import { render } from 'spec/helpers/testing-library';
import RangeFilterPlugin from './RangeFilterPlugin';
import { SingleValueType } from './SingleValueType';
import transformProps from './transformProps';

const rangeProps = {
Expand Down Expand Up @@ -118,4 +119,61 @@ describe('RangeFilterPlugin', () => {
},
});
});

it('should call setDataMask with correct greater than filter', () => {
getWrapper({ enableSingleValue: SingleValueType.Minimum });
expect(setDataMask).toHaveBeenCalledWith({
extraFormData: {
filters: [
{
col: 'SP_POP_TOTL',
op: '>=',
val: 70,
},
],
},
filterState: {
label: 'x ≥ 70',
value: [70, 100],
},
});
});

it('should call setDataMask with correct less than filter', () => {
getWrapper({ enableSingleValue: SingleValueType.Maximum });
expect(setDataMask).toHaveBeenCalledWith({
extraFormData: {
filters: [
{
col: 'SP_POP_TOTL',
op: '<=',
val: 70,
},
],
},
filterState: {
label: 'x ≤ 70',
value: [10, 70],
},
});
});

it('should call setDataMask with correct exact filter', () => {
getWrapper({ enableSingleValue: SingleValueType.Exact });
expect(setDataMask).toHaveBeenCalledWith({
extraFormData: {
filters: [
{
col: 'SP_POP_TOTL',
op: '==',
val: 10,
},
],
},
filterState: {
label: 'x = 10',
value: [10, 10],
},
});
});
});
Loading