]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16086 migrate selectlegacy in component-measures
authorJeremy Davis <jeremy.davis@sonarsource.com>
Fri, 25 Mar 2022 16:43:34 +0000 (17:43 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 30 Mar 2022 13:38:10 +0000 (13:38 +0000)
server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.tsx
server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.tsx
server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureViewSelect-test.tsx
server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureContent-test.tsx.snap
server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureViewSelect-test.tsx.snap
server/sonar-web/src/main/js/apps/component-measures/style.css

index 130abf96800823c53184d5d8a399518e09163259..fad332407d80d3cd4bedd0b877dafdf2782692e3 100644 (file)
@@ -376,7 +376,9 @@ export default class MeasureContent extends React.PureComponent<Props, State> {
                   <div className="display-flex-center">
                     {!isFileComponent && metric && (
                       <>
-                        <div>{translate('component_measures.view_as')}</div>
+                        <div id="measures-view-selection-label">
+                          {translate('component_measures.view_as')}
+                        </div>
                         <MeasureViewSelect
                           className="measure-view-select spacer-left big-spacer-right"
                           handleViewChange={this.updateView}
index c1b79eea7503edde53a3ff7a7ca1d88b7af6e54a..c215877eb7cb3dcdf03fd3c89cd7282d5b42f225 100644 (file)
@@ -18,7 +18,8 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
-import SelectLegacy from '../../../components/controls/SelectLegacy';
+import { components, OptionProps, SingleValueProps } from 'react-select';
+import Select from '../../../components/controls/Select';
 import ListIcon from '../../../components/icons/ListIcon';
 import TreeIcon from '../../../components/icons/TreeIcon';
 import TreemapIcon from '../../../components/icons/TreemapIcon';
@@ -34,10 +35,16 @@ interface Props {
   view: MeasurePageView;
 }
 
+interface ViewOption {
+  icon: JSX.Element;
+  label: string;
+  value: string;
+}
+
 export default class MeasureViewSelect extends React.PureComponent<Props> {
   getOptions = () => {
     const { metric } = this.props;
-    const options = [];
+    const options: ViewOption[] = [];
     if (hasTree(metric.key)) {
       options.push({
         icon: <TreeIcon />,
@@ -62,31 +69,41 @@ export default class MeasureViewSelect extends React.PureComponent<Props> {
     return options;
   };
 
-  handleChange = (option: { value: string }) => {
+  handleChange = (option: ViewOption) => {
     return this.props.handleViewChange(option.value as MeasurePageView);
   };
 
-  renderOption = (option: { icon: JSX.Element; label: string }) => {
-    return (
-      <>
-        {option.icon}
-        <span className="little-spacer-left">{option.label}</span>
-      </>
-    );
-  };
+  renderOption = (props: OptionProps<ViewOption, false>) => (
+    <components.Option {...props} className="display-flex-center">
+      {props.data.icon}
+      <span className="little-spacer-left">{props.data.label}</span>
+    </components.Option>
+  );
+
+  renderValue = (props: SingleValueProps<ViewOption>) => (
+    <components.SingleValue {...props} className="display-flex-center">
+      {props.data.icon}
+      <span className="little-spacer-left">{props.data.label}</span>
+    </components.SingleValue>
+  );
 
   render() {
+    const { className, view } = this.props;
+    const options = this.getOptions();
+
     return (
-      <SelectLegacy
+      <Select
+        aria-labelledby="measures-view-selection-label"
         autoBlur={true}
-        className={this.props.className}
-        clearable={false}
+        className={className}
         onChange={this.handleChange}
-        optionRenderer={this.renderOption}
-        options={this.getOptions()}
-        searchable={false}
-        value={this.props.view}
-        valueRenderer={this.renderOption}
+        components={{
+          Option: this.renderOption,
+          SingleValue: this.renderValue
+        }}
+        options={options}
+        isSearchable={false}
+        value={options.find(o => o.value === view)}
       />
     );
   }
index 557b05229d867a0bdfb22410cb6708a448a0a61f..2bb5a7086160e33f0f0e4a561f1177d0005cc672 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
+import ListIcon from '../../../../components/icons/ListIcon';
 import { mockMetric } from '../../../../helpers/testMocks';
 import { MetricKey } from '../../../../types/metrics';
 import MeasureViewSelect from '../MeasureViewSelect';
@@ -38,7 +39,7 @@ it('should render correctly', () => {
 it('should correctly trigger a selection change', () => {
   const handleViewChange = jest.fn();
   const wrapper = shallowRender({ handleViewChange });
-  wrapper.instance().handleChange({ value: 'list' });
+  wrapper.instance().handleChange({ icon: <ListIcon />, label: 'List View', value: 'list' });
   expect(handleViewChange).toBeCalledWith('list');
 });
 
index 8446a01bac01b2dc85eab32bb47b1dd0dee30ef5..46fe354db7cacc123adb3c2471618b6748617ccd 100644 (file)
@@ -162,7 +162,9 @@ exports[`should render correctly for a project 1`] = `
               className="display-flex-center"
             >
               <React.Fragment>
-                <div>
+                <div
+                  id="measures-view-selection-label"
+                >
                   component_measures.view_as
                 </div>
                 <MeasureViewSelect
@@ -371,7 +373,9 @@ exports[`should render correctly when asc prop is defined 1`] = `
               className="display-flex-center"
             >
               <React.Fragment>
-                <div>
+                <div
+                  id="measures-view-selection-label"
+                >
                   component_measures.view_as
                 </div>
                 <MeasureViewSelect
@@ -580,7 +584,9 @@ exports[`should render correctly when view prop is tree 1`] = `
               className="display-flex-center"
             >
               <React.Fragment>
-                <div>
+                <div
+                  id="measures-view-selection-label"
+                >
                   component_measures.view_as
                 </div>
                 <MeasureViewSelect
@@ -789,7 +795,9 @@ exports[`should test fetchMoreComponents to work correctly 1`] = `
               className="display-flex-center"
             >
               <React.Fragment>
-                <div>
+                <div
+                  id="measures-view-selection-label"
+                >
                   component_measures.view_as
                 </div>
                 <MeasureViewSelect
index 60095af45a3d0cd7c8723229c6bab0f1526faf17..f72fdab814b72bc8d6a44337c492f5c51a530969 100644 (file)
@@ -1,11 +1,17 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`should render correctly: has no list 1`] = `
-<SelectLegacy
+<Select
+  aria-labelledby="measures-view-selection-label"
   autoBlur={true}
-  clearable={false}
+  components={
+    Object {
+      "Option": [Function],
+      "SingleValue": [Function],
+    }
+  }
+  isSearchable={false}
   onChange={[Function]}
-  optionRenderer={[Function]}
   options={
     Array [
       Object {
@@ -20,18 +26,21 @@ exports[`should render correctly: has no list 1`] = `
       },
     ]
   }
-  searchable={false}
-  value="list"
-  valueRenderer={[Function]}
 />
 `;
 
 exports[`should render correctly: has no tree 1`] = `
-<SelectLegacy
+<Select
+  aria-labelledby="measures-view-selection-label"
   autoBlur={true}
-  clearable={false}
+  components={
+    Object {
+      "Option": [Function],
+      "SingleValue": [Function],
+    }
+  }
+  isSearchable={false}
   onChange={[Function]}
-  optionRenderer={[Function]}
   options={
     Array [
       Object {
@@ -41,18 +50,28 @@ exports[`should render correctly: has no tree 1`] = `
       },
     ]
   }
-  searchable={false}
-  value="list"
-  valueRenderer={[Function]}
+  value={
+    Object {
+      "icon": <ListIcon />,
+      "label": "component_measures.tab.list",
+      "value": "list",
+    }
+  }
 />
 `;
 
 exports[`should render correctly: has no treemap 1`] = `
-<SelectLegacy
+<Select
+  aria-labelledby="measures-view-selection-label"
   autoBlur={true}
-  clearable={false}
+  components={
+    Object {
+      "Option": [Function],
+      "SingleValue": [Function],
+    }
+  }
+  isSearchable={false}
   onChange={[Function]}
-  optionRenderer={[Function]}
   options={
     Array [
       Object {
@@ -72,8 +91,12 @@ exports[`should render correctly: has no treemap 1`] = `
       },
     ]
   }
-  searchable={false}
-  value="list"
-  valueRenderer={[Function]}
+  value={
+    Object {
+      "icon": <ListIcon />,
+      "label": "component_measures.tab.list",
+      "value": "list",
+    }
+  }
 />
 `;
index c0915cedb8fde48024daf1d06fe5421ce575903f..b4e0cdd5d32db2b638127d8664359c7e024878a8 100644 (file)
   }
 }
 
-.measure-view-select {
-  width: 102px;
-}
-
-.measure-view-select .Select-menu-outer {
-  width: 100px;
-  border-top-right-radius: 4px;
-}
-
 .measure-content-header {
   display: flex;
   align-items: center;
 }
 
+.measure-content-header .measure-view-select {
+  width: 102px;
+}
+
 .measure-content-header-left {
   flex: 1;
   min-width: 0;