]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16092 Update SelectLegacy in app and component
authorGuillaume Peoc'h <guillaume.peoch@sonarsource.com>
Wed, 30 Mar 2022 09:53:05 +0000 (11:53 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 31 Mar 2022 20:02:58 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap
server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx
server/sonar-web/src/main/js/components/controls/DateInput.tsx
server/sonar-web/src/main/js/components/controls/OutsideClickHandler.tsx
server/sonar-web/src/main/js/components/controls/__tests__/OutsideClickHandler-test.tsx
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap
server/sonar-web/src/main/js/components/controls/styles.css

index 97a10e3e5c6c4cd67833ed7a8a91970f4351af95..e663e2482f2de7dfc34c0542ce6a4570053a567c 100644 (file)
@@ -20,7 +20,7 @@
 import classNames from 'classnames';
 import * as React from 'react';
 import { fetchWebApi } from '../../../../../../api/web-api';
-import SelectLegacy from '../../../../../../components/controls/SelectLegacy';
+import Select from '../../../../../../components/controls/Select';
 import { getLocalizedMetricName, translate } from '../../../../../../helpers/l10n';
 import { Dict, Metric } from '../../../../../../types/types';
 import withMetricsContext from '../../../../metrics/withMetricsContext';
@@ -78,7 +78,7 @@ export class BadgeParams extends React.PureComponent<Props> {
   getFormatOptions = () => {
     return ['md', 'url'].map(format => ({
       label: translate('overview.badges.options.formats', format),
-      value: format
+      value: format as BadgeFormats
     }));
   };
 
@@ -102,20 +102,19 @@ export class BadgeParams extends React.PureComponent<Props> {
 
   renderBadgeType = (type: BadgeType, options: BadgeOptions) => {
     if (type === BadgeType.measure) {
+      const metricOptions = this.getMetricOptions();
       return (
         <>
           <label className="spacer-right" htmlFor="badge-metric">
             {translate('overview.badges.metric')}:
           </label>
-          <SelectLegacy
-            className="input-medium"
-            clearable={false}
-            menuStyle={{ maxHeight: 100 }}
+          <Select
+            className="input-medium it__badge-metric"
             name="badge-metric"
+            isSearchable={false}
             onChange={this.handleMetricChange}
-            options={this.getMetricOptions()}
-            searchable={false}
-            value={options.metric}
+            options={metricOptions}
+            value={metricOptions.find(o => o.value === options.metric)}
           />
         </>
       );
@@ -125,6 +124,7 @@ export class BadgeParams extends React.PureComponent<Props> {
 
   render() {
     const { className, options, type } = this.props;
+    const formatOptions = this.getFormatOptions();
     return (
       <div className={className}>
         {this.renderBadgeType(type, options)}
@@ -136,14 +136,14 @@ export class BadgeParams extends React.PureComponent<Props> {
           htmlFor="badge-format">
           {translate('format')}:
         </label>
-        <SelectLegacy
+        <Select
           className="input-medium"
-          clearable={false}
           name="badge-format"
+          isSearchable={false}
           onChange={this.handleFormatChange}
-          options={this.getFormatOptions()}
-          searchable={false}
-          value={this.props.options.format || 'md'}
+          options={formatOptions}
+          value={formatOptions.find(o => o.value === options.format)}
+          defaultValue={formatOptions.find(o => o.value === 'md')}
         />
       </div>
     );
index a9a46bf033aae86710bd8a2de320a99aedb02bb2..5134dcb90da7c2f35d48a3eb050711224c0ddc6a 100644 (file)
@@ -9,19 +9,12 @@ exports[`should display measure badge params 1`] = `
     overview.badges.metric
     :
   </label>
-  <SelectLegacy
-    className="input-medium"
-    clearable={false}
-    menuStyle={
-      Object {
-        "maxHeight": 100,
-      }
-    }
+  <Select
+    className="input-medium it__badge-metric"
+    isSearchable={false}
     name="badge-metric"
     onChange={[Function]}
     options={Array []}
-    searchable={false}
-    value="alert_status"
   />
   <label
     className="spacer-right spacer-top"
@@ -30,9 +23,15 @@ exports[`should display measure badge params 1`] = `
     format
     :
   </label>
-  <SelectLegacy
+  <Select
     className="input-medium"
-    clearable={false}
+    defaultValue={
+      Object {
+        "label": "overview.badges.options.formats.md",
+        "value": "md",
+      }
+    }
+    isSearchable={false}
     name="badge-format"
     onChange={[Function]}
     options={
@@ -47,8 +46,6 @@ exports[`should display measure badge params 1`] = `
         },
       ]
     }
-    searchable={false}
-    value="md"
   />
 </div>
 `;
@@ -62,9 +59,15 @@ exports[`should display quality gate badge params 1`] = `
     format
     :
   </label>
-  <SelectLegacy
+  <Select
     className="input-medium"
-    clearable={false}
+    defaultValue={
+      Object {
+        "label": "overview.badges.options.formats.md",
+        "value": "md",
+      }
+    }
+    isSearchable={false}
     name="badge-format"
     onChange={[Function]}
     options={
@@ -79,8 +82,6 @@ exports[`should display quality gate badge params 1`] = `
         },
       ]
     }
-    searchable={false}
-    value="md"
   />
 </div>
 `;
index 357cb797eef51a99eba7038a82113771f022bf85..1d0faa676e3a44e0159c26a6a15011ab82bdb073 100644 (file)
@@ -22,7 +22,7 @@ import * as React from 'react';
 import { translate } from '../../helpers/l10n';
 import { GraphType } from '../../types/project-activity';
 import { Metric } from '../../types/types';
-import SelectLegacy from '../controls/SelectLegacy';
+import Select from '../controls/Select';
 import AddGraphMetric from './AddGraphMetric';
 import './styles.css';
 import { getGraphTypes, isCustomGraph } from './utils';
@@ -65,13 +65,12 @@ export default class GraphsHeader extends React.PureComponent<Props> {
 
     return (
       <div className={classNames(className, 'position-relative')}>
-        <SelectLegacy
+        <Select
           className="pull-left input-medium"
-          clearable={false}
+          isSearchable={false}
           onChange={this.handleGraphChange}
           options={selectOptions}
-          searchable={false}
-          value={graph}
+          value={selectOptions.find(option => option.value === graph)}
         />
         {isCustomGraph(graph) &&
           addCustomMetric !== undefined &&
index 90414acaf87de30ffd2c6843cb9de3345c041d81..4658ac4eb5814f0e584b539904a57bf3feaf1e55 100644 (file)
@@ -31,7 +31,7 @@ import ChevronRightIcon from '../../components/icons/ChevronRightIcon';
 import { getShortMonthName, getShortWeekDayName, getWeekDayName } from '../../helpers/l10n';
 import { lazyLoadComponent } from '../lazyLoadComponent';
 import './DayPicker.css';
-import SelectLegacy from './SelectLegacy';
+import Select from './Select';
 import './styles.css';
 
 const DayPicker = lazyLoadComponent(() => import('react-day-picker'), 'DayPicker');
@@ -118,8 +118,17 @@ export default class DateInput extends React.PureComponent<Props, State> {
   };
 
   render() {
-    const { highlightFrom, highlightTo, minDate, value } = this.props;
-    const { lastHovered } = this.state;
+    const {
+      highlightFrom,
+      highlightTo,
+      minDate,
+      value,
+      name,
+      className,
+      inputClassName,
+      placeholder
+    } = this.props;
+    const { lastHovered, currentMonth, open } = this.state;
 
     const after = this.props.maxDate || new Date();
 
@@ -142,50 +151,53 @@ export default class DateInput extends React.PureComponent<Props, State> {
     const weekdaysLong = range(7).map(getWeekDayName) as Week;
     const weekdaysShort = range(7).map(getShortWeekDayName) as Week;
 
+    const monthOptions = months.map(month => ({
+      label: getShortMonthName(month),
+      value: month
+    }));
+    const yearOptions = years.map(year => ({ label: String(year), value: year }));
+
     return (
       <OutsideClickHandler onClickOutside={this.closeCalendar}>
-        <span className={classNames('date-input-control', this.props.className)}>
+        <span className={classNames('date-input-control', className)}>
           <InputWrapper
-            className={classNames('date-input-control-input', this.props.inputClassName, {
-              'is-filled': this.props.value !== undefined
+            className={classNames('date-input-control-input', inputClassName, {
+              'is-filled': value !== undefined
             })}
             innerRef={(node: HTMLInputElement | null) => (this.input = node)}
-            name={this.props.name}
+            name={name}
             onFocus={this.openCalendar}
-            placeholder={this.props.placeholder}
+            placeholder={placeholder}
             readOnly={true}
             type="text"
             value={value}
           />
           <CalendarIcon className="date-input-control-icon" fill="" />
-          {this.props.value !== undefined && (
+          {value !== undefined && (
             <ClearButton
               className="button-tiny date-input-control-reset"
               iconProps={{ size: 12 }}
               onClick={this.handleResetClick}
             />
           )}
-          {this.state.open && (
+          {open && (
             <div className="date-input-calendar">
               <nav className="date-input-calendar-nav">
                 <ButtonIcon className="button-small" onClick={this.handlePreviousMonthClick}>
                   <ChevronLeftIcon />
                 </ButtonIcon>
                 <div className="date-input-calender-month">
-                  <SelectLegacy
+                  <Select
                     className="date-input-calender-month-select"
                     onChange={this.handleCurrentMonthChange}
-                    options={months.map(month => ({
-                      label: getShortMonthName(month),
-                      value: month
-                    }))}
-                    value={this.state.currentMonth.getMonth()}
+                    options={monthOptions}
+                    value={monthOptions.find(month => month.value === currentMonth.getMonth())}
                   />
-                  <SelectLegacy
+                  <Select
                     className="date-input-calender-month-select spacer-left"
                     onChange={this.handleCurrentYearChange}
-                    options={years.map(year => ({ label: String(year), value: year }))}
-                    value={this.state.currentMonth.getFullYear()}
+                    options={yearOptions}
+                    value={yearOptions.find(year => year.value === currentMonth.getFullYear())}
                   />
                 </div>
                 <ButtonIcon className="button-small" onClick={this.handleNextMonthClick}>
@@ -197,7 +209,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
                 disabledDays={{ after, before: minDate }}
                 firstDayOfWeek={1}
                 modifiers={modifiers}
-                month={this.state.currentMonth}
+                month={currentMonth}
                 navbarElement={<NullComponent />}
                 onDayClick={this.handleDayClick}
                 onDayMouseEnter={this.handleDayMouseEnter}
index c3325f11c916e5226eda87a03de71a1ed3900d10..1fc09edfe054fce9630e53d15d71a15a8cda363e 100644 (file)
@@ -52,7 +52,11 @@ export default class OutsideClickHandler extends React.Component<Props> {
     if (this.mounted) {
       // eslint-disable-next-line react/no-find-dom-node
       const node = findDOMNode(this);
-      if (!node || !node.contains(event.target as Node)) {
+      if (
+        node &&
+        !node.contains(event.target as Node) &&
+        window.document.contains(event.target as Node)
+      ) {
         this.props.onClickOutside();
       }
     }
index 77ddcaee40e7faaeabe772976d1f4128fa299a0b..d89a951576b341fb36ef889d329f430ffd48bbc3 100644 (file)
@@ -56,6 +56,7 @@ it('should call event handler on click on window', () => {
   window.addEventListener = jest.fn((event, callback) => {
     map[event] = callback as EventListener;
   });
+  jest.spyOn(window.document, 'contains').mockReturnValue(true);
 
   mount(
     <div id="outside-element">
index 0cde2461ed50eb4dd591ca5fc5c787410acd57aa..06c3d24e5470e9da0b82f8998f33dd93bc535e79 100644 (file)
@@ -100,7 +100,7 @@ exports[`should render 3`] = `
         <div
           className="date-input-calender-month"
         >
-          <SelectLegacy
+          <Select
             className="date-input-calender-month-select"
             onChange={[Function]}
             options={
@@ -155,9 +155,14 @@ exports[`should render 3`] = `
                 },
               ]
             }
-            value={0}
+            value={
+              Object {
+                "label": "Jan",
+                "value": 0,
+              }
+            }
           />
-          <SelectLegacy
+          <Select
             className="date-input-calender-month-select spacer-left"
             onChange={[Function]}
             options={
@@ -208,7 +213,12 @@ exports[`should render 3`] = `
                 },
               ]
             }
-            value={2018}
+            value={
+              Object {
+                "label": "2018",
+                "value": 2018,
+              }
+            }
           />
         </div>
         <ButtonIcon
index 2d178d161ff5bda2843486e24a0be2c039012fdf..5e1f933b40e7cf37bf11a1b3a0c78ce4e2bef822 100644 (file)
 }
 
 .date-input-calender-month {
+  display: flex;
+  justify-content: center;
 }
 
-.date-input-calender-month-select {
+.date-input-calender-month .date-input-calender-month-select {
   width: 70px;
 }