Skip to content

Commit

Permalink
feat: add first value to Select filters
Browse files Browse the repository at this point in the history
  • Loading branch information
simcha90 committed Apr 5, 2021
1 parent 5da45bb commit 37b3f0e
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
* under the License.
*/
import {
createMultiFormatter,
Behavior,
createMultiFormatter,
DataMask,
ensureIsArray,
GenericDataType,
Expand All @@ -28,7 +28,7 @@ import {
} from '@superset-ui/core';
import React, { useEffect, useState } from 'react';
import { Select } from 'src/common/components';
import { PluginFilterSelectProps } from './types';
import { FIRST_VALUE, PluginFilterSelectProps, SelectValue } from './types';
import { StyledSelect, Styles } from '../common';
import { getDataRecordFormatter, getSelectExtraFormData } from '../../utils';

Expand Down Expand Up @@ -70,13 +70,25 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
inputRef,
defaultToFirstItem,
} = formData;

const isDefaultToFirstItemInFilterConfigModal =
place === Place.FILTER_CONFIG_MODAL && defaultToFirstItem;

const groupby = ensureIsArray<string>(formData.groupby);
const initValues = defaultValue ?? [];
const firstItem: (string | number)[] = data[0]
? (groupby.map(col => data[0][col]) as string[]) ?? initValues
: initValues;
const [values, setValues] = useState<(string | number | boolean)[]>(
defaultToFirstItem ? firstItem : initValues,
// Correct initial value for Ant Select
const initSelectValue: SelectValue =
// `defaultValue` can be `FIRST_VALUE` if `defaultToFirstItem` is checked, so need convert it to correct value for Select
defaultValue === FIRST_VALUE ? [] : defaultValue ?? [];

const firstItem: SelectValue = data[0]
? (groupby.map(col => data[0][col]) as string[]) ?? initSelectValue
: initSelectValue;

// If we are in config modal we always need show empty select for `defaultToFirstItem`
const [values, setValues] = useState<SelectValue>(
defaultToFirstItem && place !== Place.FILTER_CONFIG_MODAL
? firstItem
: initSelectValue,
);

const [col] = groupby;
Expand All @@ -85,26 +97,33 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
timeFormatter,
});

const handleChange = (
value?: (number | string)[] | number | string | null,
) => {
const resultValue: (number | string)[] = ensureIsArray<number | string>(
value,
);
setValues(resultValue);
const handleChange = (value?: SelectValue | number | string) => {
let selectValue: (number | string)[];
if (value === FIRST_VALUE) {
selectValue = isDefaultToFirstItemInFilterConfigModal ? [] : firstItem;
} else {
selectValue = ensureIsArray<number | string>(value);
}
setValues(selectValue);

const emptyFilter =
enableEmptyFilter && !inverseSelection && resultValue?.length === 0;
enableEmptyFilter && !inverseSelection && selectValue?.length === 0;

// Set currentState value for a case of non-`defaultToFirstItem`
const stateValue = selectValue.length ? selectValue : null;

const dataMask = {
extraFormData: getSelectExtraFormData(
col,
resultValue,
selectValue,
emptyFilter,
inverseSelection,
),
currentState: {
value: resultValue.length ? resultValue : null,
// We need to save in state `FIRST_VALUE` as some const and not as REAL value,
// because when FiltersBar check if all filters initialized it compares `defaultValue` with this value
// and because REAL value can be unpredictable for users that have different data for same dashboard we use `FIRST_VALUE`
value: value === FIRST_VALUE ? FIRST_VALUE : stateValue,
},
};

Expand All @@ -121,7 +140,12 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
};

useEffect(() => {
handleChange(currentValue ?? []);
// For currentValue we need set always `FIRST_VALUE` only if we in config modal for `defaultToFirstItem` mode
handleChange(
isDefaultToFirstItemInFilterConfigModal
? FIRST_VALUE
: currentValue ?? [],
);
}, [
JSON.stringify(currentValue),
defaultToFirstItem,
Expand All @@ -130,15 +154,9 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
inverseSelection,
]);

const isDefaultToFirstItemInFilterConfigModal =
place === Place.FILTER_CONFIG_MODAL && defaultToFirstItem;

useEffect(() => {
let resultValue = defaultToFirstItem ? firstItem : initValues;
if (isDefaultToFirstItemInFilterConfigModal) {
resultValue = null;
}
handleChange(resultValue);
// If we have `defaultToFirstItem` mode it means that default value always `FIRST_VALUE`
handleChange(defaultToFirstItem ? FIRST_VALUE : defaultValue);
}, [
JSON.stringify(defaultValue),
JSON.stringify(firstItem),
Expand Down
7 changes: 5 additions & 2 deletions superset-frontend/src/filters/components/Select/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ import {
import { RefObject } from 'react';
import { PluginFilterStylesProps } from '../types';

export const FIRST_VALUE = '__FIRST_VALUE__';
export type SelectValue = (number | string)[] | null;

interface PluginFilterSelectCustomizeProps {
defaultValue?: (string | number)[] | null;
currentValue?: (string | number)[] | null;
defaultValue?: SelectValue | typeof FIRST_VALUE;
currentValue?: SelectValue | typeof FIRST_VALUE;
enableEmptyFilter: boolean;
inverseSelection: boolean;
multiSelect: boolean;
Expand Down

0 comments on commit 37b3f0e

Please sign in to comment.