You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by jo...@apache.org on 2023/06/15 20:27:50 UTC

[superset] branch master updated: feat: Allows new values for single value filters (#24388)

This is an automated email from the ASF dual-hosted git repository.

johnbodley 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 dc042c6c3d feat: Allows new values for single value filters (#24388)
dc042c6c3d is described below

commit dc042c6c3dbd2f8a1a2f24648ec36bbe9133d493
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Thu Jun 15 17:27:42 2023 -0300

    feat: Allows new values for single value filters (#24388)
---
 .../components/Select/SelectFilterPlugin.tsx       | 66 ++++++++++++----------
 1 file changed, 35 insertions(+), 31 deletions(-)

diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
index 50f87b655d..0ebcb03a5d 100644
--- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
@@ -21,7 +21,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
 import {
   AppSection,
   DataMask,
-  DataRecordValue,
   ensureIsArray,
   ExtraFormData,
   GenericDataType,
@@ -36,7 +35,7 @@ import debounce from 'lodash/debounce';
 import { useImmerReducer } from 'use-immer';
 import { Select } from 'src/components';
 import { SLOW_DEBOUNCE } from 'src/constants';
-import { propertyComparator } from 'src/components/Select/utils';
+import { hasOption, propertyComparator } from 'src/components/Select/utils';
 import { FilterBarOrientation } from 'src/dashboard/types';
 import { uniqWith, isEqual } from 'lodash';
 import { PluginFilterSelectProps, SelectValue } from './types';
@@ -109,6 +108,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
   );
   const [col] = groupby;
   const [initialColtypeMap] = useState(coltypeMap);
+  const [search, setSearch] = useState('');
   const [dataMask, dispatchDataMask] = useImmerReducer(reducer, {
     extraFormData: {},
     filterState,
@@ -168,29 +168,25 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
   const isDisabled =
     appSection === AppSection.FILTER_CONFIG_MODAL && defaultToFirstItem;
 
-  const debouncedOwnStateFunc = useCallback(
-    debounce((val: string) => {
-      dispatchDataMask({
-        type: 'ownState',
-        ownState: {
-          coltypeMap: initialColtypeMap,
-          search: val,
-        },
-      });
-    }, SLOW_DEBOUNCE),
-    [],
-  );
-
-  const searchWrapper = useCallback(
-    (val: string) => {
-      if (searchAllOptions) {
-        debouncedOwnStateFunc(val);
-      }
-    },
-    [debouncedOwnStateFunc, searchAllOptions],
+  const onSearch = useMemo(
+    () =>
+      debounce((search: string) => {
+        setSearch(search);
+        if (searchAllOptions) {
+          dispatchDataMask({
+            type: 'ownState',
+            ownState: {
+              coltypeMap: initialColtypeMap,
+              search,
+            },
+          });
+        }
+      }, SLOW_DEBOUNCE),
+    [dispatchDataMask, initialColtypeMap, searchAllOptions],
   );
 
   const clearSuggestionSearch = useCallback(() => {
+    setSearch('');
     if (searchAllOptions) {
       dispatchDataMask({
         type: 'ownState',
@@ -236,20 +232,29 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
     return undefined;
   }, [filterState.validateMessage, filterState.validateStatus]);
 
-  const options = useMemo(() => {
+  const uniqueOptions = useMemo(() => {
     const allOptions = [...data];
-    const uniqueOptions = uniqWith(allOptions, isEqual);
-    const selectOptions: { label: string; value: DataRecordValue }[] = [];
-    uniqueOptions.forEach(row => {
+    return uniqWith(allOptions, isEqual).map(row => {
       const [value] = groupby.map(col => row[col]);
-      selectOptions.push({
+      return {
         label: labelFormatter(value, datatype),
         value,
-      });
+        isNewOption: false,
+      };
     });
-    return selectOptions;
   }, [data, datatype, groupby, labelFormatter]);
 
+  const options = useMemo(() => {
+    if (search && !multiSelect && !hasOption(search, uniqueOptions, true)) {
+      uniqueOptions.unshift({
+        label: search,
+        value: search,
+        isNewOption: true,
+      });
+    }
+    return uniqueOptions;
+  }, [multiSelect, search, uniqueOptions]);
+
   const sortComparator = useCallback(
     (a: AntdLabeledValue, b: AntdLabeledValue) => {
       const labelComparator = propertyComparator('label');
@@ -317,7 +322,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
           showSearch={showSearch}
           mode={multiSelect ? 'multiple' : 'single'}
           placeholder={placeholderText}
-          onSearch={searchWrapper}
+          onSearch={onSearch}
           onSelect={clearSuggestionSearch}
           onBlur={handleBlur}
           onFocus={setFocusedFilter}
@@ -329,7 +334,6 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
           loading={isRefreshing}
           oneLine={filterBarOrientation === FilterBarOrientation.HORIZONTAL}
           invertSelection={inverseSelection}
-          // @ts-ignore
           options={options}
           sortComparator={sortComparator}
           onDropdownVisibleChange={setFilterActive}