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

tai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 31cc415  fix: keep placeholder in multivalue select when a value 
exists (#11181)
31cc415 is described below

commit 31cc4155b7e195e6aee1874a68577e0d55d10d77
Author: Elizabeth Thompson <[email protected]>
AuthorDate: Tue Oct 13 13:45:31 2020 -0700

    fix: keep placeholder in multivalue select when a value exists (#11181)
---
 .../explore/components/SelectControl_spec.jsx      | 67 +++++++++++++++-------
 superset-frontend/src/components/Select/styles.tsx | 44 +++++++++++++-
 .../components/controls/AdhocFilterControl.jsx     |  2 +-
 .../explore/components/controls/MetricsControl.jsx |  6 +-
 4 files changed, 94 insertions(+), 25 deletions(-)

diff --git 
a/superset-frontend/spec/javascripts/explore/components/SelectControl_spec.jsx 
b/superset-frontend/spec/javascripts/explore/components/SelectControl_spec.jsx
index 5409da2..76ca694 100644
--- 
a/superset-frontend/spec/javascripts/explore/components/SelectControl_spec.jsx
+++ 
b/superset-frontend/spec/javascripts/explore/components/SelectControl_spec.jsx
@@ -19,7 +19,7 @@
 /* eslint-disable no-unused-expressions */
 import React from 'react';
 import sinon from 'sinon';
-import { shallow } from 'enzyme';
+import { shallow, mount } from 'enzyme';
 import { Select, CreatableSelect } from 'src/components/Select';
 import OnPasteSelect from 'src/components/Select/OnPasteSelect';
 import SelectControl from 'src/explore/components/controls/SelectControl';
@@ -47,25 +47,6 @@ describe('SelectControl', () => {
     wrapper = shallow(<SelectControl {...defaultProps} />);
   });
 
-  it('renders with Select by default', () => {
-    expect(wrapper.find(OnPasteSelect)).not.toExist();
-    expect(wrapper.findWhere(x => x.type() === Select)).toHaveLength(1);
-  });
-
-  it('renders with OnPasteSelect when multi', () => {
-    wrapper.setProps({ multi: true });
-    expect(wrapper.find(OnPasteSelect)).toExist();
-    expect(wrapper.findWhere(x => x.type() === Select)).toHaveLength(0);
-  });
-
-  it('renders with Creatable when freeForm', () => {
-    wrapper.setProps({ freeForm: true });
-    expect(wrapper.find(OnPasteSelect)).not.toExist();
-    expect(wrapper.findWhere(x => x.type() === CreatableSelect)).toHaveLength(
-      1,
-    );
-  });
-
   it('uses Select in onPasteSelect when freeForm=false', () => {
     wrapper = shallow(<SelectControl {...defaultProps} multi />);
     const select = wrapper.find(OnPasteSelect);
@@ -100,6 +81,52 @@ describe('SelectControl', () => {
     expect(selectAllProps.onChange.calledWith(expectedValues)).toBe(true);
   });
 
+  describe('render', () => {
+    it('renders with Select by default', () => {
+      expect(wrapper.find(OnPasteSelect)).not.toExist();
+      expect(wrapper.findWhere(x => x.type() === Select)).toHaveLength(1);
+    });
+
+    it('renders with OnPasteSelect when multi', () => {
+      wrapper.setProps({ multi: true });
+      expect(wrapper.find(OnPasteSelect)).toExist();
+      expect(wrapper.findWhere(x => x.type() === Select)).toHaveLength(0);
+    });
+
+    it('renders with Creatable when freeForm', () => {
+      wrapper.setProps({ freeForm: true });
+      expect(wrapper.find(OnPasteSelect)).not.toExist();
+      expect(wrapper.findWhere(x => x.type() === 
CreatableSelect)).toHaveLength(
+        1,
+      );
+    });
+    describe('when select is multi', () => {
+      it('renders the placeholder when a selection has been made', () => {
+        wrapper = mount(
+          <SelectControl
+            {...defaultProps}
+            multi
+            value={50}
+            placeholder="add something"
+          />,
+        );
+        expect(wrapper.html()).toContain('add something');
+      });
+    });
+    describe('when select is single', () => {
+      it('does not render the placeholder when a selection has been made', () 
=> {
+        wrapper = mount(
+          <SelectControl
+            {...defaultProps}
+            value={50}
+            placeholder="add something"
+          />,
+        );
+        expect(wrapper.html()).not.toContain('add something');
+      });
+    });
+  });
+
   describe('getOptions', () => {
     it('returns the correct options', () => {
       wrapper.setProps(defaultProps);
diff --git a/superset-frontend/src/components/Select/styles.tsx 
b/superset-frontend/src/components/Select/styles.tsx
index e5f844a..73436f7 100644
--- a/superset-frontend/src/components/Select/styles.tsx
+++ b/superset-frontend/src/components/Select/styles.tsx
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import React, { CSSProperties } from 'react';
+import React, { CSSProperties, ComponentType } from 'react';
 import { css, SerializedStyles, ClassNames } from '@emotion/core';
 import { supersetTheme } from '@superset-ui/core';
 import {
@@ -241,9 +241,39 @@ export const DEFAULT_STYLES: PartialStylesConfig = {
   }),
 };
 
-const { ClearIndicator, DropdownIndicator, Option } = defaultComponents;
+const multiInputSpanStyle = css`
+  color: '#879399',
+  position: 'absolute',
+  top: '2px',
+  left: '4px',
+  width: '100vw',
+`;
 
-export const DEFAULT_COMPONENTS: SelectComponentsConfig<any> = {
+const { ClearIndicator, DropdownIndicator, Option, Input } = defaultComponents;
+
+type SelectComponentsType = SelectComponentsConfig<any> & {
+  Input: ComponentType<InputProps>;
+};
+
+// react-select is missing selectProps from their props type
+// so overwriting it here to avoid errors
+type InputProps = {
+  selectProps: {
+    isMulti: boolean;
+    value: {
+      length: number;
+    };
+    placeholder: string;
+  };
+  cx: (a: string | null, b: any, c: string) => string | void;
+  innerRef: (element: React.Ref<any>) => void;
+  isHidden: boolean;
+  isDisabled?: boolean | undefined;
+  className?: string | undefined;
+  getStyles: any;
+};
+
+export const DEFAULT_COMPONENTS: SelectComponentsType = {
   Option: ({ children, innerProps, data, ...props }) => (
     <ClassNames>
       {({ css }) => (
@@ -272,6 +302,14 @@ export const DEFAULT_COMPONENTS: 
SelectComponentsConfig<any> = {
       />
     </DropdownIndicator>
   ),
+  Input: (props: InputProps) => (
+    <div style={{ position: 'relative' }}>
+      <Input {...props} />
+      {!!(props.selectProps.isMulti && props.selectProps.value.length) && (
+        <span css={multiInputSpanStyle}>{props.selectProps.placeholder}</span>
+      )}
+    </div>
+  ),
 };
 
 export const VALUE_LABELED_STYLES: PartialStylesConfig = {
diff --git 
a/superset-frontend/src/explore/components/controls/AdhocFilterControl.jsx 
b/superset-frontend/src/explore/components/controls/AdhocFilterControl.jsx
index 13f8d87..e0a5779 100644
--- a/superset-frontend/src/explore/components/controls/AdhocFilterControl.jsx
+++ b/superset-frontend/src/explore/components/controls/AdhocFilterControl.jsx
@@ -267,7 +267,7 @@ export default class AdhocFilterControl extends 
React.Component {
         <OnPasteSelect
           isMulti
           name={`select-${this.props.name}`}
-          placeholder={t('choose a column or metric')}
+          placeholder={t('choose one or more column or metric')}
           options={this.state.options}
           value={this.state.values}
           labelKey="label"
diff --git 
a/superset-frontend/src/explore/components/controls/MetricsControl.jsx 
b/superset-frontend/src/explore/components/controls/MetricsControl.jsx
index ad1a320..a73159e 100644
--- a/superset-frontend/src/explore/components/controls/MetricsControl.jsx
+++ b/superset-frontend/src/explore/components/controls/MetricsControl.jsx
@@ -337,7 +337,11 @@ export default class MetricsControl extends 
React.PureComponent {
         <OnPasteSelect
           isMulti={this.props.multi}
           name={`select-${this.props.name}`}
-          placeholder={t('choose a column or aggregate function')}
+          placeholder={
+            this.props.multi
+              ? t('choose one or more column or aggregate function')
+              : t('choose a column or aggregate function')
+          }
           options={this.state.options}
           value={this.state.value}
           labelKey="label"

Reply via email to