Skip to content

Commit

Permalink
fix(native-filters): handle null values in value filter (apache#16460)
Browse files Browse the repository at this point in the history
* fix(native-filters): handle null values in value filter

* lint
  • Loading branch information
villebro authored Aug 26, 2021
1 parent 1badcae commit 1c71eda
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 9 deletions.
1 change: 0 additions & 1 deletion superset-frontend/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ type PickedSelectProps = Pick<
AntdSelectAllProps,
| 'allowClear'
| 'autoFocus'
| 'value'
| 'disabled'
| 'filterOption'
| 'notFoundContent'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import {
AppSection,
DataMask,
DataRecordValue,
ensureIsArray,
ExtraFormData,
GenericDataType,
Expand All @@ -36,7 +37,11 @@ import { useImmerReducer } from 'use-immer';
import { FormItemProps } from 'antd/lib/form';
import { PluginFilterSelectProps, SelectValue } from './types';
import { StyledFormItem, FilterPluginStyle, StatusMessage } from '../common';
import { getDataRecordFormatter, getSelectExtraFormData } from '../../utils';
import {
formatFilterValue,
getDataRecordFormatter,
getSelectExtraFormData,
} from '../../utils';

type DataMaskAction =
| { type: 'ownState'; ownState: JsonObject }
Expand Down Expand Up @@ -119,7 +124,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
filterState: {
...filterState,
label: values?.length
? `${(values || []).join(', ')}${suffix}`
? `${(values || []).map(formatFilterValue).join(', ')}${suffix}`
: undefined,
value:
appSection === AppSection.FILTER_CONFIG_MODAL && defaultToFirstItem
Expand Down Expand Up @@ -249,12 +254,12 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
}

const options = useMemo(() => {
const options: { label: string; value: string | number }[] = [];
const options: { label: string; value: DataRecordValue }[] = [];
data.forEach(row => {
const [value] = groupby.map(col => row[col]);
options.push({
label: labelFormatter(value, datatype),
value: typeof value === 'number' ? value : String(value),
value,
});
});
return options;
Expand Down Expand Up @@ -286,6 +291,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
loading={isRefreshing}
maxTagCount={5}
invertSelection={inverseSelection}
// @ts-ignore
options={options}
/>
</StyledFormItem>
Expand Down
18 changes: 17 additions & 1 deletion superset-frontend/src/filters/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { FALSE_STRING, NULL_STRING, TRUE_STRING } from 'src/utils/common';

export const getSelectExtraFormData = (
col: string,
value?: null | (string | number)[],
value?: null | (string | number | boolean | null)[],
emptyFilter = false,
inverseSelection = false,
): ExtraFormData => {
Expand All @@ -46,6 +46,7 @@ export const getSelectExtraFormData = (
{
col,
op: inverseSelection ? ('NOT IN' as const) : ('IN' as const),
// @ts-ignore
val: value,
},
];
Expand Down Expand Up @@ -116,3 +117,18 @@ export function getDataRecordFormatter({
return String(value);
};
}

export function formatFilterValue(
value: string | number | boolean | null,
): string {
if (value === null) {
return NULL_STRING;
}
if (typeof value === 'string') {
return value;
}
if (typeof value === 'number') {
return String(value);
}
return value ? TRUE_STRING : FALSE_STRING;
}
7 changes: 4 additions & 3 deletions superset/utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ def cast_to_num(value: Optional[Union[float, int, str]]) -> Optional[Union[float
return None


def cast_to_boolean(value: Any) -> bool:
def cast_to_boolean(value: Any) -> Optional[bool]:
"""Casts a value to an int/float
>>> cast_to_boolean(1)
Expand All @@ -473,12 +473,13 @@ def cast_to_boolean(value: Any) -> bool:
>>> cast_to_boolean('False')
False
>>> cast_to_boolean(None)
False
:param value: value to be converted to boolean representation
:returns: value cast to `bool`. when value is 'true' or value that are not 0
converte into True
converted into True. Return `None` if value is `None`
"""
if value is None:
return None
if isinstance(value, (int, float)):
return value != 0
if isinstance(value, str):
Expand Down

0 comments on commit 1c71eda

Please sign in to comment.