This is an automated email from the ASF dual-hosted git repository.
villebro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 468638c feat(native-filters): Add default first value to select
filter (#13726)
468638c is described below
commit 468638c5b824449f24dd019b05fcc9c596789e27
Author: simcha90 <[email protected]>
AuthorDate: Mon Apr 12 09:22:33 2021 +0300
feat(native-filters): Add default first value to select filter (#13726)
* feat: native filters first default value
* fix: fix CR notes
* feat: add support for `Place` type
* refactor: sync with master
* feat: add first value to Select filters
* refactor: fix CR notes
* refactor: updates usage of `ownFilters` to `ownState`
* Revert "refactor: updates usage of `ownFilters` to `ownState`"
This reverts commit 58b91998
* fix: revert mocks
* fix: fix CR notes
* chore: update package json
* chore: update package json
* chore: update package json
* test: fix tests
* fix: fix BE empty metrics
* lint: fix lint
* fix: fix BE empty metrics
* refactor: fix Cr notes
---
.../FiltersConfigForm/DefaultValue.tsx | 8 ++-
.../components/Select/SelectFilterPlugin.tsx | 62 +++++++++++++++++-----
.../src/filters/components/Select/controlPanel.ts | 14 +++++
.../filters/components/Select/transformProps.ts | 11 +++-
.../src/filters/components/Select/types.ts | 11 +++-
5 files changed, 88 insertions(+), 18 deletions(-)
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
index b1d347c..34fd7c0 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
@@ -17,7 +17,12 @@
* under the License.
*/
import React, { FC, useEffect, useState } from 'react';
-import { Behavior, SetDataMaskHook, SuperChart } from '@superset-ui/core';
+import {
+ Behavior,
+ SetDataMaskHook,
+ SuperChart,
+ AppSection,
+} from '@superset-ui/core';
import { FormInstance } from 'antd/lib/form';
import Loading from 'src/components/Loading';
import { NativeFiltersForm } from '../types';
@@ -56,6 +61,7 @@ const DefaultValue: FC<DefaultValueProps> = ({
<SuperChart
height={25}
width={250}
+ appSection={AppSection.FILTER_CONFIG_MODAL}
behaviors={[Behavior.NATIVE_FILTER]}
formData={formData}
// For charts that don't have datasource we need workaround for empty
placeholder
diff --git
a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
index 6c5291c..da0bdf1 100644
--- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
@@ -17,6 +17,7 @@
* under the License.
*/
import {
+ AppSection,
Behavior,
DataMask,
ensureIsArray,
@@ -27,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';
@@ -42,6 +43,7 @@ export default function PluginFilterSelect(props:
PluginFilterSelectProps) {
width,
behaviors,
setDataMask,
+ appSection,
} = props;
const {
defaultValue,
@@ -51,12 +53,28 @@ export default function PluginFilterSelect(props:
PluginFilterSelectProps) {
currentValue,
inverseSelection,
inputRef,
+ defaultToFirstItem,
} = formData;
- const [values, setValues] = useState<(string | number | boolean)[]>(
- defaultValue ?? [],
- );
+ const forceFirstValue =
+ appSection === AppSection.FILTER_CONFIG_MODAL && defaultToFirstItem;
+
const groupby = ensureIsArray<string>(formData.groupby);
+ // 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 && appSection !== AppSection.FILTER_CONFIG_MODAL
+ ? firstItem
+ : initSelectValue,
+ );
const [col] = groupby;
const datatype: GenericDataType = coltypeMap[col];
@@ -64,26 +82,36 @@ export default function PluginFilterSelect(props:
PluginFilterSelectProps) {
timeFormatter: smartDateDetailedFormatter,
});
- const handleChange = (
- value?: (number | string)[] | number | string | null,
- ) => {
- const resultValue: (number | string)[] = ensureIsArray<number | string>(
+ const handleChange = (value?: SelectValue | number | string) => {
+ let selectValue: (number | string)[] = ensureIsArray<number | string>(
value,
);
- setValues(resultValue);
+ let stateValue: SelectValue | typeof FIRST_VALUE = selectValue.length
+ ? selectValue
+ : null;
+
+ if (value === FIRST_VALUE) {
+ selectValue = forceFirstValue ? [] : firstItem;
+ stateValue = FIRST_VALUE;
+ }
+
+ setValues(selectValue);
const emptyFilter =
- enableEmptyFilter && !inverseSelection && resultValue?.length === 0;
+ enableEmptyFilter && !inverseSelection && selectValue?.length === 0;
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: stateValue,
},
};
@@ -100,18 +128,23 @@ 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(forceFirstValue ? FIRST_VALUE : currentValue ?? []);
}, [
JSON.stringify(currentValue),
+ defaultToFirstItem,
multiSelect,
enableEmptyFilter,
inverseSelection,
]);
useEffect(() => {
- handleChange(defaultValue ?? []);
+ // If we have `defaultToFirstItem` mode it means that default value always
`FIRST_VALUE`
+ handleChange(defaultToFirstItem ? FIRST_VALUE : defaultValue);
}, [
JSON.stringify(defaultValue),
+ JSON.stringify(firstItem),
+ defaultToFirstItem,
multiSelect,
enableEmptyFilter,
inverseSelection,
@@ -127,6 +160,7 @@ export default function PluginFilterSelect(props:
PluginFilterSelectProps) {
allowClear
// @ts-ignore
value={values}
+ disabled={forceFirstValue}
showSearch={showSearch}
mode={multiSelect ? 'multiple' : undefined}
placeholder={placeholderText}
diff --git a/superset-frontend/src/filters/components/Select/controlPanel.ts
b/superset-frontend/src/filters/components/Select/controlPanel.ts
index eddcd29..c4a560b 100644
--- a/superset-frontend/src/filters/components/Select/controlPanel.ts
+++ b/superset-frontend/src/filters/components/Select/controlPanel.ts
@@ -24,6 +24,7 @@ const {
enableEmptyFilter,
inverseSelection,
multiSelect,
+ defaultToFirstItem,
sortAscending,
} = DEFAULT_FORM_DATA;
@@ -81,6 +82,19 @@ const config: ControlPanelConfig = {
],
[
{
+ name: 'defaultToFirstItem',
+ config: {
+ type: 'CheckboxControl',
+ label: t('Default to first item'),
+ default: defaultToFirstItem,
+ resetConfig: true,
+ renderTrigger: true,
+ description: t('Select first item by default'),
+ },
+ },
+ ],
+ [
+ {
name: 'inverseSelection',
config: {
type: 'CheckboxControl',
diff --git a/superset-frontend/src/filters/components/Select/transformProps.ts
b/superset-frontend/src/filters/components/Select/transformProps.ts
index 59262b3..4bf27d0 100644
--- a/superset-frontend/src/filters/components/Select/transformProps.ts
+++ b/superset-frontend/src/filters/components/Select/transformProps.ts
@@ -22,7 +22,15 @@ import { DEFAULT_FORM_DATA, PluginFilterSelectChartProps }
from './types';
export default function transformProps(
chartProps: PluginFilterSelectChartProps,
) {
- const { formData, height, hooks, queriesData, width, behaviors } =
chartProps;
+ const {
+ formData,
+ height,
+ hooks,
+ queriesData,
+ width,
+ behaviors,
+ appSection,
+ } = chartProps;
const newFormData = { ...DEFAULT_FORM_DATA, ...formData };
const { setDataMask = () => {} } = hooks;
const [queryData] = queriesData;
@@ -34,6 +42,7 @@ export default function transformProps(
return {
coltypeMap,
+ appSection,
width,
behaviors,
height,
diff --git a/superset-frontend/src/filters/components/Select/types.ts
b/superset-frontend/src/filters/components/Select/types.ts
index ddd2c60..8542e98 100644
--- a/superset-frontend/src/filters/components/Select/types.ts
+++ b/superset-frontend/src/filters/components/Select/types.ts
@@ -17,6 +17,7 @@
* under the License.
*/
import {
+ AppSection,
ChartProps,
Behavior,
DataRecord,
@@ -28,12 +29,16 @@ 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;
+ defaultToFirstItem: boolean;
inputRef?: RefObject<HTMLInputElement>;
sortAscending: boolean;
}
@@ -51,6 +56,7 @@ export type PluginFilterSelectProps = PluginFilterStylesProps
& {
data: DataRecord[];
setDataMask: SetDataMaskHook;
behaviors: Behavior[];
+ appSection: AppSection;
formData: PluginFilterSelectQueryFormData;
};
@@ -59,6 +65,7 @@ export const DEFAULT_FORM_DATA:
PluginFilterSelectCustomizeProps = {
currentValue: null,
enableEmptyFilter: false,
inverseSelection: false,
+ defaultToFirstItem: false,
multiSelect: true,
sortAscending: true,
};