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,
 };

Reply via email to