Browse Source

SONAR-15655 Change Project perspective and sorting to use react-select@v5

tags/9.3.0.51899
Mathieu Suen 2 years ago
parent
commit
0ab80061f0
100 changed files with 790 additions and 780 deletions
  1. 4
    2
      server/sonar-web/package.json
  2. 2
    2
      server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts
  3. 3
    3
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx
  4. 3
    3
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap
  5. 2
    2
      server/sonar-web/src/main/js/apps/application-console/ProjectBranchRow.tsx
  6. 1
    1
      server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ProjectBranchRow-test.tsx.snap
  7. 2
    2
      server/sonar-web/src/main/js/apps/application-settings/ReportFrequencyForm.tsx
  8. 2
    2
      server/sonar-web/src/main/js/apps/application-settings/__tests__/ReportFrequencyForm-test.tsx
  9. 3
    3
      server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ReportFrequencyForm-test.tsx.snap
  10. 2
    2
      server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.tsx
  11. 2
    2
      server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.tsx
  12. 2
    2
      server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx
  13. 3
    2
      server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/WorkersForm-test.tsx
  14. 2
    2
      server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap
  15. 3
    3
      server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx
  16. 2
    2
      server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx
  17. 4
    4
      server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx
  18. 10
    10
      server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/ActivationFormModal-test.tsx.snap
  19. 1
    1
      server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap
  20. 6
    6
      server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/CustomRuleFormModal-test.tsx.snap
  21. 2
    2
      server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.tsx
  22. 3
    3
      server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureViewSelect-test.tsx.snap
  23. 3
    3
      server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
  24. 2
    2
      server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-test.tsx
  25. 2
    2
      server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx
  26. 1
    1
      server/sonar-web/src/main/js/apps/permissions/project/components/__tests__/__snapshots__/ApplyTemplate-test.tsx.snap
  27. 2
    2
      server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.tsx
  28. 1
    1
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityPageHeader-test.tsx.snap
  29. 2
    2
      server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisListRenderer.tsx
  30. 3
    3
      server/sonar-web/src/main/js/apps/projectBaseline/components/__tests__/__snapshots__/BranchAnalysisListRenderer-test.tsx.snap
  31. 2
    2
      server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx
  32. 3
    3
      server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/ProjectQualityGateAppRenderer-test.tsx
  33. 6
    6
      server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/__snapshots__/ProjectQualityGateAppRenderer-test.tsx.snap
  34. 3
    3
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx
  35. 2
    2
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx
  36. 3
    3
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx
  37. 3
    3
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx
  38. 2
    2
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/AddLanguageModal-test.tsx.snap
  39. 3
    3
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/SetQualityProfileModal-test.tsx.snap
  40. 36
    11
      server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelect.tsx
  41. 0
    74
      server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelectOption.tsx
  42. 45
    14
      server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.tsx
  43. 0
    70
      server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.tsx
  44. 27
    8
      server/sonar-web/src/main/js/apps/projects/components/__tests__/PerspectiveSelect-test.tsx
  45. 0
    80
      server/sonar-web/src/main/js/apps/projects/components/__tests__/PerspectiveSelectOption-test.tsx
  46. 41
    37
      server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelect-test.tsx
  47. 0
    80
      server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelectOption-test.tsx
  48. 38
    12
      server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.tsx.snap
  49. 0
    33
      server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelectOption-test.tsx.snap
  50. 107
    45
      server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelect-test.tsx.snap
  51. 0
    25
      server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelectOption-test.tsx.snap
  52. 2
    2
      server/sonar-web/src/main/js/apps/projects/filters/SearchableFilterFooter.tsx
  53. 3
    2
      server/sonar-web/src/main/js/apps/projects/filters/__tests__/SearchableFilterFooter-test.tsx
  54. 2
    2
      server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx
  55. 3
    3
      server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx
  56. 3
    1
      server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx
  57. 4
    4
      server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap
  58. 3
    3
      server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap
  59. 2
    2
      server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx
  60. 2
    2
      server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx
  61. 2
    2
      server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
  62. 2
    2
      server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx
  63. 2
    2
      server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx
  64. 4
    3
      server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ThresholdInput-test.tsx
  65. 1
    1
      server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionOperator-test.tsx.snap
  66. 1
    1
      server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/MetricSelect-test.tsx.snap
  67. 5
    5
      server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap
  68. 2
    2
      server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.tsx
  69. 2
    2
      server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.tsx
  70. 2
    2
      server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.tsx
  71. 2
    2
      server/sonar-web/src/main/js/apps/quality-profiles/details/ProfilePermissionsFormSelect.tsx
  72. 1
    1
      server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ChangeParentForm-test.tsx.snap
  73. 1
    1
      server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfilePermissionsFormSelect-test.tsx.snap
  74. 3
    3
      server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx
  75. 2
    2
      server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.tsx
  76. 4
    4
      server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/CreateProfileForm-test.tsx.snap
  77. 1
    1
      server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/ProfilesListHeader-test.tsx.snap
  78. 3
    3
      server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
  79. 3
    3
      server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx
  80. 9
    9
      server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
  81. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/Languages.tsx
  82. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/__tests__/Languages-test.tsx
  83. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/__tests__/__snapshots__/Languages-test.tsx.snap
  84. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.tsx
  85. 3
    2
      server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/InputForSingleSelectList-test.tsx
  86. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx
  87. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx
  88. 6
    6
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap
  89. 2
    2
      server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.tsx
  90. 2
    2
      server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearch-test.tsx.snap
  91. 2
    2
      server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx
  92. 3
    3
      server/sonar-web/src/main/js/components/controls/DateInput.tsx
  93. 2
    2
      server/sonar-web/src/main/js/components/controls/SearchSelect.tsx
  94. 127
    31
      server/sonar-web/src/main/js/components/controls/Select.tsx
  95. 0
    0
      server/sonar-web/src/main/js/components/controls/SelectLegacy.css
  96. 59
    0
      server/sonar-web/src/main/js/components/controls/SelectLegacy.tsx
  97. 8
    51
      server/sonar-web/src/main/js/components/controls/__tests__/Select-test.tsx
  98. 85
    0
      server/sonar-web/src/main/js/components/controls/__tests__/SelectLegacy-test.tsx
  99. 2
    2
      server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap
  100. 0
    0
      server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.tsx.snap

+ 4
- 2
server/sonar-web/package.json View File

@@ -37,7 +37,8 @@
"react-modal": "3.14.3",
"react-redux": "5.1.1",
"react-router": "3.2.6",
"react-select": "1.2.1",
"react-select": "4.3.1",
"react-select-legacy": "npm:react-select@1.2.1",
"react-virtualized": "9.21.2",
"redux": "4.0.5",
"redux-thunk": "2.3.0",
@@ -80,7 +81,8 @@
"@types/react-modal": "3.12.1",
"@types/react-redux": "6.0.6",
"@types/react-router": "3.0.20",
"@types/react-select": "1.2.6",
"@types/react-select": "4.0.16",
"@types/react-select-legacy": "npm:@types/react-select@1.2.6",
"@types/react-virtualized": "9.21.0",
"@types/sanitize-html": "1.22.0",
"@types/valid-url": "1.0.2",

+ 2
- 2
server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts View File

@@ -40,7 +40,7 @@ import RadioToggle from '../../../components/controls/RadioToggle';
import ReloadButton from '../../../components/controls/ReloadButton';
import SearchBox from '../../../components/controls/SearchBox';
import SearchSelect from '../../../components/controls/SearchSelect';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import SelectList, { SelectListFilter } from '../../../components/controls/SelectList';
import SimpleModal from '../../../components/controls/SimpleModal';
import Tooltip from '../../../components/controls/Tooltip';
@@ -219,7 +219,7 @@ const exposeLibraries = () => {
SearchBox,
SearchSelect,
SecurityHotspotIcon,
Select,
SelectLegacy,
SelectList,
SelectListFilter,
SimpleModal,

+ 3
- 3
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx View File

@@ -20,7 +20,7 @@
import classNames from 'classnames';
import * as React from 'react';
import { fetchWebApi } from '../../../../../../api/web-api';
import Select from '../../../../../../components/controls/Select';
import SelectLegacy from '../../../../../../components/controls/SelectLegacy';
import { getLocalizedMetricName, translate } from '../../../../../../helpers/l10n';
import { BadgeFormats, BadgeOptions, BadgeType } from './utils';

@@ -105,7 +105,7 @@ export default class BadgeParams extends React.PureComponent<Props> {
<label className="spacer-right" htmlFor="badge-metric">
{translate('overview.badges.metric')}:
</label>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
menuStyle={{ maxHeight: 100 }}
@@ -135,7 +135,7 @@ export default class BadgeParams extends React.PureComponent<Props> {
htmlFor="badge-format">
{translate('format')}:
</label>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
name="badge-format"

+ 3
- 3
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap View File

@@ -9,7 +9,7 @@ exports[`should display measure badge params 1`] = `
overview.badges.metric
:
</label>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
menuStyle={
@@ -30,7 +30,7 @@ exports[`should display measure badge params 1`] = `
format
:
</label>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
name="badge-format"
@@ -62,7 +62,7 @@ exports[`should display quality gate badge params 1`] = `
format
:
</label>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
name="badge-format"

+ 2
- 2
server/sonar-web/src/main/js/apps/application-console/ProjectBranchRow.tsx View File

@@ -21,7 +21,7 @@ import { orderBy } from 'lodash';
import * as React from 'react';
import { getBranches } from '../../api/branches';
import Checkbox from '../../components/controls/Checkbox';
import Select from '../../components/controls/Select';
import SelectLegacy from '../../components/controls/SelectLegacy';
import Tooltip from '../../components/controls/Tooltip';
import QualifierIcon from '../../components/icons/QualifierIcon';
import DeferredSpinner from '../../components/ui/DeferredSpinner';
@@ -117,7 +117,7 @@ export default class ProjectBranchRow extends React.PureComponent<Props, State>
</Tooltip>
</td>
<td>
<Select
<SelectLegacy
className="width100"
clearable={false}
disabled={!checked}

+ 1
- 1
server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ProjectBranchRow-test.tsx.snap View File

@@ -30,7 +30,7 @@ exports[`Should render correctly 1`] = `
</Tooltip>
</td>
<td>
<Select
<SelectLegacy
className="width100"
clearable={false}
disabled={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/application-settings/ReportFrequencyForm.tsx View File

@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import { Button, ResetButtonLink } from '../../components/controls/buttons';
import Select from '../../components/controls/Select';
import SelectLegacy from '../../components/controls/SelectLegacy';
import { translate } from '../../helpers/l10n';
import { sanitizeStringRestricted } from '../../helpers/sanitize';
import { SettingCategoryDefinition } from '../../types/settings';
@@ -61,7 +61,7 @@ export default function ReportFrequencyForm(props: ReportFrequencyFormProps) {
/>
)}

<Select
<SelectLegacy
className="input-medium"
clearable={false}
name={definition.name}

+ 2
- 2
server/sonar-web/src/main/js/apps/application-settings/__tests__/ReportFrequencyForm-test.tsx View File

@@ -20,7 +20,7 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { Button, ResetButtonLink } from '../../../components/controls/buttons';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { mockDefinition } from '../../../helpers/mocks/settings';
import ReportFrequencyForm, { ReportFrequencyFormProps } from '../ReportFrequencyForm';

@@ -34,7 +34,7 @@ it('should handle changes', () => {
const onSave = jest.fn();
const wrapper = shallowRender({ onSave });

wrapper.find(Select).simulate('change', { value: 'Daily' });
wrapper.find(SelectLegacy).simulate('change', { value: 'Daily' });

expect(wrapper.find('.button-success').exists()).toBe(true);
expect(wrapper.find(ResetButtonLink).exists()).toBe(true);

+ 3
- 3
server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ReportFrequencyForm-test.tsx.snap View File

@@ -13,7 +13,7 @@ exports[`should render correctly: changed 1`] = `
}
}
/>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
onChange={[Function]}
@@ -61,7 +61,7 @@ exports[`should render correctly: default 1`] = `
}
}
/>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
onChange={[Function]}
@@ -94,7 +94,7 @@ exports[`should render correctly: no description 1`] = `
<h2>
application_settings.report.frequency
</h2>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
onChange={[Function]}

+ 2
- 2
server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { translate } from '../../../helpers/l10n';
import { TaskStatuses } from '../../../types/tasks';
import { STATUSES } from '../constants';
@@ -48,7 +48,7 @@ export default class StatusFilter extends React.PureComponent<Props> {
];

return (
<Select
<SelectLegacy
className="input-medium"
clearable={false}
onChange={this.handleChange}

+ 2
- 2
server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { translate } from '../../../helpers/l10n';
import { ALL_TYPES } from '../constants';

@@ -48,7 +48,7 @@ export default class TypesFilter extends React.PureComponent<Props> {
];

return (
<Select
<SelectLegacy
className="input-large"
clearable={false}
onChange={this.handleChange}

+ 2
- 2
server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx View File

@@ -21,7 +21,7 @@ import * as React from 'react';
import { setWorkerCount } from '../../../api/ce';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { Alert } from '../../../components/ui/Alert';
import { translate } from '../../../helpers/l10n';

@@ -96,7 +96,7 @@ export default class WorkersForm extends React.PureComponent<Props, State> {
</header>
<form onSubmit={this.handleSubmit}>
<div className="modal-body">
<Select
<SelectLegacy
className="input-tiny spacer-top"
clearable={false}
onChange={this.handleWorkerCountChange}

+ 3
- 2
server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/WorkersForm-test.tsx View File

@@ -24,6 +24,7 @@ jest.mock('../../../../api/ce', () => ({

import { shallow } from 'enzyme';
import * as React from 'react';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { submit } from '../../../../helpers/testUtils';
import WorkersForm from '../WorkersForm';

@@ -31,7 +32,7 @@ it('changes select', () => {
const wrapper = shallow(<WorkersForm onClose={jest.fn()} workerCount={1} />);
expect(wrapper).toMatchSnapshot();

wrapper.find('Select').prop<Function>('onChange')({ value: 7 });
wrapper.find(SelectLegacy).prop<Function>('onChange')({ value: 7 });
wrapper.update();
expect(wrapper).toMatchSnapshot();
});
@@ -40,7 +41,7 @@ it('returns new worker count', async () => {
const onClose = jest.fn();
const wrapper = shallow(<WorkersForm onClose={onClose} workerCount={1} />);
(wrapper.instance() as WorkersForm).mounted = true;
wrapper.find('Select').prop<Function>('onChange')({ value: 7 });
wrapper.find(SelectLegacy).prop<Function>('onChange')({ value: 7 });

wrapper.update();
submit(wrapper.find('form'));

+ 2
- 2
server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap View File

@@ -18,7 +18,7 @@ exports[`changes select 1`] = `
<div
className="modal-body"
>
<Select
<SelectLegacy
className="input-tiny spacer-top"
clearable={false}
onChange={[Function]}
@@ -114,7 +114,7 @@ exports[`changes select 2`] = `
<div
className="modal-body"
>
<Select
<SelectLegacy
className="input-tiny spacer-top"
clearable={false}
onChange={[Function]}

+ 3
- 3
server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx View File

@@ -22,7 +22,7 @@ import * as React from 'react';
import { activateRule, Profile } from '../../../api/quality-profiles';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import SeverityHelper from '../../../components/shared/SeverityHelper';
import { Alert } from '../../../components/ui/Alert';
import { SEVERITIES } from '../../../helpers/constants';
@@ -166,7 +166,7 @@ export default class ActivationFormModal extends React.PureComponent<Props, Stat

<div className="modal-field">
<label>{translate('coding_rules.quality_profile')}</label>
<Select
<SelectLegacy
className="js-profile"
clearable={false}
disabled={submitting || profilesWithDepth.length === 1}
@@ -180,7 +180,7 @@ export default class ActivationFormModal extends React.PureComponent<Props, Stat
</div>
<div className="modal-field">
<label>{translate('severity')}</label>
<Select
<SelectLegacy
className="js-severity"
clearable={false}
disabled={submitting}

+ 2
- 2
server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx View File

@@ -21,7 +21,7 @@ import * as React from 'react';
import { bulkActivateRules, bulkDeactivateRules, Profile } from '../../../api/quality-profiles';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { Alert } from '../../../components/ui/Alert';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { formatMeasure } from '../../../helpers/measures';
@@ -182,7 +182,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
value: profile.key
}));
return (
<Select
<SelectLegacy
multi={true}
onChange={this.handleProfileSelect}
options={options}

+ 4
- 4
server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx View File

@@ -22,7 +22,7 @@ import { createRule, updateRule } from '../../../api/rules';
import FormattingTips from '../../../components/common/FormattingTips';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import SeverityHelper from '../../../components/shared/SeverityHelper';
import TypeHelper from '../../../components/shared/TypeHelper';
import { Alert } from '../../../components/ui/Alert';
@@ -218,7 +218,7 @@ export default class CustomRuleFormModal extends React.PureComponent<Props, Stat
renderTypeField = () => (
<div className="modal-field flex-1 spacer-right">
<label htmlFor="coding-rules-custom-rule-type">{translate('type')}</label>
<Select
<SelectLegacy
clearable={false}
disabled={this.state.submitting}
id="coding-rules-custom-rule-type"
@@ -240,7 +240,7 @@ export default class CustomRuleFormModal extends React.PureComponent<Props, Stat
renderSeverityField = () => (
<div className="modal-field flex-1 spacer-right">
<label htmlFor="coding-rules-custom-rule-severity">{translate('severity')}</label>
<Select
<SelectLegacy
clearable={false}
disabled={this.state.submitting}
id="coding-rules-custom-rule-severity"
@@ -262,7 +262,7 @@ export default class CustomRuleFormModal extends React.PureComponent<Props, Stat
<label htmlFor="coding-rules-custom-rule-status">
{translate('coding_rules.filters.status')}
</label>
<Select
<SelectLegacy
clearable={false}
disabled={this.state.submitting}
id="coding-rules-custom-rule-status"

+ 10
- 10
server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/ActivationFormModal-test.tsx.snap View File

@@ -30,7 +30,7 @@ exports[`should render correctly: custom rule 1`] = `
<label>
coding_rules.quality_profile
</label>
<Select
<SelectLegacy
className="js-profile"
clearable={false}
disabled={false}
@@ -45,7 +45,7 @@ exports[`should render correctly: custom rule 1`] = `
<label>
severity
</label>
<Select
<SelectLegacy
className="js-severity"
clearable={false}
disabled={false}
@@ -139,7 +139,7 @@ exports[`should render correctly: default 1`] = `
<label>
coding_rules.quality_profile
</label>
<Select
<SelectLegacy
className="js-profile"
clearable={false}
disabled={false}
@@ -154,7 +154,7 @@ exports[`should render correctly: default 1`] = `
<label>
severity
</label>
<Select
<SelectLegacy
className="js-severity"
clearable={false}
disabled={false}
@@ -283,7 +283,7 @@ exports[`should render correctly: submitting 1`] = `
<label>
coding_rules.quality_profile
</label>
<Select
<SelectLegacy
className="js-profile"
clearable={false}
disabled={true}
@@ -298,7 +298,7 @@ exports[`should render correctly: submitting 1`] = `
<label>
severity
</label>
<Select
<SelectLegacy
className="js-severity"
clearable={false}
disabled={true}
@@ -425,7 +425,7 @@ exports[`should render correctly: update mode 1`] = `
<label>
coding_rules.quality_profile
</label>
<Select
<SelectLegacy
className="js-profile"
clearable={false}
disabled={false}
@@ -440,7 +440,7 @@ exports[`should render correctly: update mode 1`] = `
<label>
severity
</label>
<Select
<SelectLegacy
className="js-severity"
clearable={false}
disabled={false}
@@ -564,7 +564,7 @@ exports[`should render correctly: with deep profiles 1`] = `
<label>
coding_rules.quality_profile
</label>
<Select
<SelectLegacy
className="js-profile"
clearable={false}
disabled={true}
@@ -586,7 +586,7 @@ exports[`should render correctly: with deep profiles 1`] = `
<label>
severity
</label>
<Select
<SelectLegacy
className="js-severity"
clearable={false}
disabled={false}

+ 1
- 1
server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap View File

@@ -171,7 +171,7 @@ exports[`should render correctly: no profile pre-selected 1`] = `
coding_rules.activate_in
</label>
</h3>
<Select
<SelectLegacy
multi={true}
onChange={[Function]}
options={Array []}

+ 6
- 6
server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/CustomRuleFormModal-test.tsx.snap View File

@@ -76,7 +76,7 @@ exports[`should handle re-activation 1`] = `
>
type
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
id="coding-rules-custom-rule-type"
@@ -115,7 +115,7 @@ exports[`should handle re-activation 1`] = `
>
severity
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
id="coding-rules-custom-rule-severity"
@@ -158,7 +158,7 @@ exports[`should handle re-activation 1`] = `
>
coding_rules.filters.status
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
id="coding-rules-custom-rule-status"
@@ -345,7 +345,7 @@ exports[`should render correctly: default 1`] = `
>
type
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
id="coding-rules-custom-rule-type"
@@ -384,7 +384,7 @@ exports[`should render correctly: default 1`] = `
>
severity
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
id="coding-rules-custom-rule-severity"
@@ -427,7 +427,7 @@ exports[`should render correctly: default 1`] = `
>
coding_rules.filters.status
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
id="coding-rules-custom-rule-status"

+ 2
- 2
server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import ListIcon from '../../../components/icons/ListIcon';
import TreeIcon from '../../../components/icons/TreeIcon';
import TreemapIcon from '../../../components/icons/TreemapIcon';
@@ -76,7 +76,7 @@ export default class MeasureViewSelect extends React.PureComponent<Props> {

render() {
return (
<Select
<SelectLegacy
autoBlur={true}
className={this.props.className}
clearable={false}

+ 3
- 3
server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureViewSelect-test.tsx.snap View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: has no list 1`] = `
<Select
<SelectLegacy
autoBlur={true}
clearable={false}
onChange={[Function]}
@@ -27,7 +27,7 @@ exports[`should render correctly: has no list 1`] = `
`;

exports[`should render correctly: has no tree 1`] = `
<Select
<SelectLegacy
autoBlur={true}
clearable={false}
onChange={[Function]}
@@ -48,7 +48,7 @@ exports[`should render correctly: has no tree 1`] = `
`;

exports[`should render correctly: has no treemap 1`] = `
<Select
<SelectLegacy
autoBlur={true}
clearable={false}
onChange={[Function]}

+ 3
- 3
server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx View File

@@ -29,7 +29,7 @@ import HelpTooltip from '../../../components/controls/HelpTooltip';
import Modal from '../../../components/controls/Modal';
import Radio from '../../../components/controls/Radio';
import SearchSelect from '../../../components/controls/SearchSelect';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import Tooltip from '../../../components/controls/Tooltip';
import IssueTypeIcon from '../../../components/icons/IssueTypeIcon';
import SeverityHelper from '../../../components/shared/SeverityHelper';
@@ -356,7 +356,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
);

const input = (
<Select
<SelectLegacy
className="input-super-large"
clearable={true}
onChange={this.handleSelectFieldChange('type')}
@@ -385,7 +385,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
}));

const input = (
<Select
<SelectLegacy
className="input-super-large"
clearable={true}
onChange={this.handleSelectFieldChange('severity')}

+ 2
- 2
server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-test.tsx View File

@@ -21,7 +21,7 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { searchIssueTags } from '../../../../api/issues';
import { SubmitButton } from '../../../../components/controls/buttons';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { mockIssue } from '../../../../helpers/testMocks';
import { change, waitAndUpdate } from '../../../../helpers/testUtils';
import BulkChangeModal, { MAX_PAGE_SIZE } from '../BulkChangeModal';
@@ -113,7 +113,7 @@ it('should disable the submit button unless some change is configured', async ()
expect(wrapper.find(SubmitButton).props().disabled).toBe(true);

const { onChange } = wrapper
.find(Select)
.find(SelectLegacy)
.at(0)
.props();
if (!onChange) {

+ 2
- 2
server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx View File

@@ -20,7 +20,7 @@
import * as React from 'react';
import { applyTemplateToProject, getPermissionTemplates } from '../../../../api/permissions';
import { ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import SimpleModal from '../../../../components/controls/SimpleModal';
import { Alert } from '../../../../components/ui/Alert';
import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
@@ -125,7 +125,7 @@ export default class ApplyTemplate extends React.PureComponent<Props, State> {
<MandatoryFieldMarker />
</label>
{this.state.permissionTemplates && (
<Select
<SelectLegacy
clearable={false}
id="project-permissions-template"
onChange={this.handlePermissionTemplateChange}

+ 1
- 1
server/sonar-web/src/main/js/apps/permissions/project/components/__tests__/__snapshots__/ApplyTemplate-test.tsx.snap View File

@@ -43,7 +43,7 @@ exports[`render correctly 2`] = `
template
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
id="project-permissions-template"
onChange={[Function]}

+ 2
- 2
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.tsx View File

@@ -19,7 +19,7 @@
*/
import classNames from 'classnames';
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { translate } from '../../../helpers/l10n';
import { APPLICATION_EVENT_TYPES, EVENT_TYPES, Query } from '../utils';
import ProjectActivityDateInput from './ProjectActivityDateInput';
@@ -48,7 +48,7 @@ export default class ProjectActivityPageHeader extends React.PureComponent<Props
return (
<header className="page-header">
{!['VW', 'SVW'].includes(this.props.project.qualifier) && (
<Select
<SelectLegacy
className={classNames('pull-left big-spacer-right', {
'input-medium': !isApp,
'input-large': isApp

+ 1
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityPageHeader-test.tsx.snap View File

@@ -4,7 +4,7 @@ exports[`should render correctly the list of series 1`] = `
<header
className="page-header"
>
<Select
<SelectLegacy
className="pull-left big-spacer-right input-medium"
clearable={true}
onChange={[Function]}

+ 2
- 2
server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisListRenderer.tsx View File

@@ -20,7 +20,7 @@
import classNames from 'classnames';
import * as React from 'react';
import Radio from '../../../components/controls/Radio';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import Tooltip from '../../../components/controls/Tooltip';
import DateFormatter from '../../../components/intl/DateFormatter';
import TimeFormatter from '../../../components/intl/TimeFormatter';
@@ -98,7 +98,7 @@ export default function BranchAnalysisListRenderer(props: BranchAnalysisListRend
<>
<div className="spacer-bottom">
{translate('baseline.analysis_from')}
<Select
<SelectLegacy
autoBlur={true}
className="input-medium spacer-left"
clearable={false}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectBaseline/components/__tests__/__snapshots__/BranchAnalysisListRenderer-test.tsx.snap View File

@@ -6,7 +6,7 @@ exports[`should render correctly: Analyses 1`] = `
className="spacer-bottom"
>
baseline.analysis_from
<Select
<SelectLegacy
autoBlur={true}
className="input-medium spacer-left"
clearable={false}
@@ -302,7 +302,7 @@ exports[`should render correctly: empty 1`] = `
className="spacer-bottom"
>
baseline.analysis_from
<Select
<SelectLegacy
autoBlur={true}
className="input-medium spacer-left"
clearable={false}
@@ -346,7 +346,7 @@ exports[`should render correctly: loading 1`] = `
className="spacer-bottom"
>
baseline.analysis_from
<Select
<SelectLegacy
autoBlur={true}
className="input-medium spacer-left"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx View File

@@ -27,7 +27,7 @@ import DisableableSelectOption from '../../components/common/DisableableSelectOp
import { SubmitButton } from '../../components/controls/buttons';
import HelpTooltip from '../../components/controls/HelpTooltip';
import Radio from '../../components/controls/Radio';
import Select from '../../components/controls/Select';
import SelectLegacy from '../../components/controls/SelectLegacy';
import { Alert } from '../../components/ui/Alert';
import { translate } from '../../helpers/l10n';
import { isDiffMetric } from '../../helpers/measures';
@@ -146,7 +146,7 @@ export default function ProjectQualityGateAppRenderer(props: ProjectQualityGateA
{translate('project_quality_gate.always_use_specific')}
</div>
<div className="display-flex-center">
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={submitting || usesDefault}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/ProjectQualityGateAppRenderer-test.tsx View File

@@ -20,7 +20,7 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import Radio from '../../../components/controls/Radio';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { mockQualityGate } from '../../../helpers/mocks/quality-gates';
import { mockCondition } from '../../../helpers/testMocks';
import { submit } from '../../../helpers/testUtils';
@@ -57,7 +57,7 @@ it('should render correctly', () => {
it('should render select options correctly', () => {
return new Promise<void>(resolve => {
const wrapper = shallowRender();
const render = wrapper.find(Select).props().optionRenderer;
const render = wrapper.find(SelectLegacy).props().optionRenderer;

expect(render).toBeDefined();

@@ -87,7 +87,7 @@ it('should correctly handle changes', () => {
.onCheck('1');
expect(onSelect).toHaveBeenLastCalledWith('1');

wrapper.find(Select).props().onChange!({ value: '2' });
wrapper.find(SelectLegacy).props().onChange!({ value: '2' });
expect(onSelect).toHaveBeenLastCalledWith('2');
});


+ 6
- 6
server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/__snapshots__/ProjectQualityGateAppRenderer-test.tsx.snap View File

@@ -107,7 +107,7 @@ exports[`should render correctly: always use system default 1`] = `
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={true}
@@ -257,7 +257,7 @@ exports[`should render correctly: default 1`] = `
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={false}
@@ -413,7 +413,7 @@ exports[`should render correctly: show new code warning 1`] = `
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={false}
@@ -593,7 +593,7 @@ exports[`should render correctly: show warning 1`] = `
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={false}
@@ -749,7 +749,7 @@ exports[`should render correctly: show warning if not using default 1`] = `
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={true}
@@ -905,7 +905,7 @@ exports[`should render correctly: submitting 1`] = `
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={true}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx View File

@@ -24,7 +24,7 @@ import { Link } from 'react-router';
import { Profile } from '../../../api/quality-profiles';
import DisableableSelectOption from '../../../components/common/DisableableSelectOption';
import { ButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import SimpleModal from '../../../components/controls/SimpleModal';
import { translate } from '../../../helpers/l10n';
import { getQualityProfileUrl } from '../../../helpers/urls';
@@ -85,7 +85,7 @@ export function AddLanguageModal(props: AddLanguageModalProps) {
{translate('project_quality_profile.add_language_modal.choose_language')}
</label>
</div>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={submitting}
@@ -102,7 +102,7 @@ export function AddLanguageModal(props: AddLanguageModalProps) {
{translate('project_quality_profile.add_language_modal.choose_profile')}
</label>
</div>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={submitting || !language}

+ 2
- 2
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx View File

@@ -23,7 +23,7 @@ import { Profile } from '../../../api/quality-profiles';
import DisableableSelectOption from '../../../components/common/DisableableSelectOption';
import { ButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Radio from '../../../components/controls/Radio';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import SimpleModal from '../../../components/controls/SimpleModal';
import { Alert } from '../../../components/ui/Alert';
import { translate, translateWithParameters } from '../../../helpers/l10n';
@@ -119,7 +119,7 @@ export default function SetQualityProfileModal(props: SetQualityProfileModalProp
{translate('project_quality_profile.always_use_specific')}
</div>
<div className="display-flex-center">
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={submitting || hasSelectedSysDefault}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import SimpleModal from '../../../../components/controls/SimpleModal';
import { mockQualityProfile } from '../../../../helpers/testMocks';
import { AddLanguageModal, AddLanguageModalProps } from '../AddLanguageModal';
@@ -95,13 +95,13 @@ function diveIntoSimpleModal(wrapper: ShallowWrapper) {

function getLanguageSelect(wrapper: ShallowWrapper) {
return diveIntoSimpleModal(wrapper)
.find(Select)
.find(SelectLegacy)
.at(0);
}

function getProfileSelect(wrapper: ShallowWrapper) {
return diveIntoSimpleModal(wrapper)
.find(Select)
.find(SelectLegacy)
.at(1);
}


+ 3
- 3
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx View File

@@ -20,7 +20,7 @@
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
import Radio from '../../../../components/controls/Radio';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import SimpleModal from '../../../../components/controls/SimpleModal';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockQualityProfile } from '../../../../helpers/testMocks';
@@ -35,7 +35,7 @@ it('should render correctly', () => {
it('should render select options correctly', () => {
return new Promise<void>((resolve, reject) => {
const wrapper = shallowRender();
const render = wrapper.find(Select).props().optionRenderer;
const render = wrapper.find(SelectLegacy).props().optionRenderer;
if (!render) {
reject();
return;
@@ -66,7 +66,7 @@ it('should correctly handle changes', () => {
expect(onSubmit).toHaveBeenLastCalledWith('foo', 'foo');

const change = diveIntoSimpleModal(wrapper)
.find(Select)
.find(SelectLegacy)
.props().onChange;

expect(change).toBeDefined();

+ 2
- 2
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/AddLanguageModal-test.tsx.snap View File

@@ -28,7 +28,7 @@ Array [
project_quality_profile.add_language_modal.choose_language
</label>
</div>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={false}
@@ -61,7 +61,7 @@ Array [
project_quality_profile.add_language_modal.choose_profile
</label>
</div>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={true}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/SetQualityProfileModal-test.tsx.snap View File

@@ -68,7 +68,7 @@ Array [
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={false}
@@ -182,7 +182,7 @@ Array [
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={true}
@@ -296,7 +296,7 @@ Array [
<div
className="display-flex-center"
>
<Select
<SelectLegacy
className="abs-width-300"
clearable={false}
disabled={false}

+ 36
- 11
server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelect.tsx View File

@@ -17,11 +17,14 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { omit } from 'lodash';
import * as React from 'react';
import { components, OptionProps } from 'react-select';
import Select from '../../../components/controls/Select';
import BubblesIcon from '../../../components/icons/BubblesIcon';
import ListIcon from '../../../components/icons/ListIcon';
import { translate } from '../../../helpers/l10n';
import { VIEWS, VISUALIZATIONS } from '../utils';
import PerspectiveSelectOption, { Option } from './PerspectiveSelectOption';

interface Props {
className?: string;
@@ -30,19 +33,38 @@ interface Props {
visualization?: string;
}

export interface PerspectiveOption {
type: string;
value: string;
label: string;
}

export default class PerspectiveSelect extends React.PureComponent<Props> {
handleChange = (option: Option) => {
if (option.type === 'view') {
handleChange = (option: PerspectiveOption) => {
if (option && option.type === 'view') {
this.props.onChange({ view: option.value });
} else if (option.type === 'visualization') {
} else if (option && option.type === 'visualization') {
this.props.onChange({ view: 'visualizations', visualization: option.value });
}
};

perspectiveOptionRender = (props: OptionProps<PerspectiveOption, false>) => {
const { data, className } = props;
return (
<components.Option
{...omit(props, ['children', 'className'])}
className={`it__projects-perspective-option-${data.value} ${className}`}>
{data.type === 'view' && <ListIcon className="little-spacer-right" />}
{data.type === 'visualization' && <BubblesIcon className="little-spacer-right" />}
{props.children}
</components.Option>
);
};

render() {
const { view, visualization } = this.props;
const perspective = view === 'visualizations' ? visualization : view;
const options = [
const options: PerspectiveOption[] = [
...VIEWS.map(opt => ({
type: 'view',
value: opt.value,
@@ -56,15 +78,18 @@ export default class PerspectiveSelect extends React.PureComponent<Props> {
];
return (
<div className={this.props.className}>
<label>{translate('projects.perspective')}:</label>
<label id="aria-projects-perspective">{translate('projects.perspective')}:</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-perspective"
className="little-spacer-left input-medium it__projects-perspective-select"
isClearable={false}
onChange={this.handleChange}
optionComponent={PerspectiveSelectOption}
components={{
Option: this.perspectiveOptionRender
}}
options={options}
searchable={false}
value={perspective}
isSearchable={false}
value={options.find(option => option.value === perspective)}
/>
</div>
);

+ 0
- 74
server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelectOption.tsx View File

@@ -1,74 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2021 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import BubblesIcon from '../../../components/icons/BubblesIcon';
import ListIcon from '../../../components/icons/ListIcon';

export interface Option {
label: string;
type: string;
value: string;
}

interface Props {
option: Option;
children?: React.ReactNode;
className?: string;
isFocused?: boolean;
onFocus: (option: Option, event: React.SyntheticEvent<HTMLElement>) => void;
onSelect: (option: Option, event: React.SyntheticEvent<HTMLElement>) => void;
}

export default class PerspectiveSelectOption extends React.PureComponent<Props> {
handleMouseDown = (event: React.SyntheticEvent<HTMLElement>) => {
event.preventDefault();
event.stopPropagation();
this.props.onSelect(this.props.option, event);
};

handleMouseEnter = (event: React.SyntheticEvent<HTMLElement>) => {
this.props.onFocus(this.props.option, event);
};

handleMouseMove = (event: React.SyntheticEvent<HTMLElement>) => {
if (this.props.isFocused) {
return;
}
this.props.onFocus(this.props.option, event);
};

render() {
const { option } = this.props;
return (
<div
className={this.props.className}
onMouseDown={this.handleMouseDown}
onMouseEnter={this.handleMouseEnter}
onMouseMove={this.handleMouseMove}
title={option.label}>
<div>
{option.type === 'view' && <ListIcon className="little-spacer-right" />}
{option.type === 'visualization' && <BubblesIcon className="little-spacer-right" />}
{this.props.children}
</div>
</div>
);
}
}

+ 45
- 14
server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.tsx View File

@@ -17,8 +17,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { sortBy } from 'lodash';
import { omit, sortBy } from 'lodash';
import * as React from 'react';
import { components, OptionProps } from 'react-select';
import { colors } from '../../../app/theme';
import { ButtonIcon } from '../../../components/controls/buttons';
import Select from '../../../components/controls/Select';
@@ -27,7 +28,6 @@ import SortAscIcon from '../../../components/icons/SortAscIcon';
import SortDescIcon from '../../../components/icons/SortDescIcon';
import { translate } from '../../../helpers/l10n';
import { parseSorting, SORTING_LEAK_METRICS, SORTING_METRICS } from '../utils';
import ProjectsSortingSelectOption, { Option } from './ProjectsSortingSelectOption';

interface Props {
className?: string;
@@ -37,8 +37,19 @@ interface Props {
view: string;
}

export interface Option {
label: string;
value: string;
className?: string;
short?: string;
}

export default class ProjectsSortingSelect extends React.PureComponent<Props> {
getSorting = () => parseSorting(this.props.selectedSort);
getSorting = () => {
const options = this.getOptions();
const { sortDesc, sortValue } = parseSorting(this.props.selectedSort);
return { sortDesc, value: options.find(o => o.value === sortValue) };
};

getOptions = () => {
const sortMetrics = this.props.view === 'leak' ? SORTING_LEAK_METRICS : SORTING_METRICS;
@@ -46,39 +57,59 @@ export default class ProjectsSortingSelect extends React.PureComponent<Props> {
option => ({
value: option.value,
label: translate('projects.sorting', option.value),
class: option.class
className: option.class
})
);
};

handleDescToggle = () => {
const sorting = this.getSorting();
this.props.onChange(sorting.sortValue, !sorting.sortDesc);
const { sortDesc, sortValue } = parseSorting(this.props.selectedSort);
this.props.onChange(sortValue, !sortDesc);
};

handleSortChange = (option: Option) =>
handleSortChange = (option: Option) => {
this.props.onChange(option.value, this.getSorting().sortDesc);
};

projectsSortingSelectOption = (props: OptionProps<Option, false>) => {
const { data, children } = props;
return (
<components.Option
{...omit(props, ['children'])}
className={`it__project-sort-option-${data.value} ${data.className}`}>
{data.short ? data.short : children}
</components.Option>
);
};

render() {
const { sortDesc, sortValue } = this.getSorting();
const { sortDesc, value } = this.getSorting();

return (
<div className={this.props.className}>
<label>{translate('projects.sort_by')}:</label>
<label id="aria-projects-sort">{translate('projects.sort_by')}:</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-sort"
className="little-spacer-left input-medium it__projects-sort-select"
isClearable={false}
onChange={this.handleSortChange}
optionComponent={ProjectsSortingSelectOption}
components={{
Option: this.projectsSortingSelectOption
}}
options={this.getOptions()}
searchable={false}
value={sortValue}
isSearchable={false}
value={value}
/>
<Tooltip
overlay={
sortDesc ? translate('projects.sort_descending') : translate('projects.sort_ascending')
}>
<ButtonIcon
aria-label={
sortDesc
? translate('projects.sort_descending')
: translate('projects.sort_ascending')
}
className="js-projects-sorting-invert spacer-left"
color={colors.gray60}
onClick={this.handleDescToggle}>

+ 0
- 70
server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.tsx View File

@@ -1,70 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2021 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import classNames from 'classnames';
import * as React from 'react';

export interface Option {
label: string;
value: string;
class?: string;
short?: string;
}

interface Props {
option: Option;
children?: React.ReactNode;
className?: string;
isFocused?: boolean;
onFocus: (option: Option, event: React.SyntheticEvent<HTMLElement>) => void;
onSelect: (option: Option, event: React.SyntheticEvent<HTMLElement>) => void;
}

export default class ProjectsSortingSelectOption extends React.PureComponent<Props> {
handleMouseDown = (event: React.SyntheticEvent<HTMLElement>) => {
event.preventDefault();
event.stopPropagation();
this.props.onSelect(this.props.option, event);
};

handleMouseEnter = (event: React.SyntheticEvent<HTMLElement>) => {
this.props.onFocus(this.props.option, event);
};

handleMouseMove = (event: React.SyntheticEvent<HTMLElement>) => {
if (this.props.isFocused) {
return;
}
this.props.onFocus(this.props.option, event);
};

render() {
const { option } = this.props;
return (
<div
className={classNames(this.props.className, option.class)}
onMouseDown={this.handleMouseDown}
onMouseEnter={this.handleMouseEnter}
onMouseMove={this.handleMouseMove}
title={option.label}>
{option.short ? option.short : this.props.children}
</div>
);
}
}

+ 27
- 8
server/sonar-web/src/main/js/apps/projects/components/__tests__/PerspectiveSelect-test.tsx View File

@@ -19,6 +19,9 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import BubblesIcon from '../../../../components/icons/BubblesIcon';
import ListIcon from '../../../../components/icons/ListIcon';
import { mockReactSelectOptionProps } from '../../../../helpers/mocks/react-select';
import PerspectiveSelect from '../PerspectiveSelect';

it('should render correctly', () => {
@@ -26,20 +29,36 @@ it('should render correctly', () => {
});

it('should render with coverage selected', () => {
expect(
shallow(
<PerspectiveSelect onChange={jest.fn()} view="visualizations" visualization="coverage" />
)
).toMatchSnapshot();
expect(shallowRender({ view: 'visualizations', visualization: 'coverage' })).toMatchSnapshot();
});

it('should render option correctly', () => {
const wrapper = shallowRender();
const OptionRender = wrapper.instance().perspectiveOptionRender;
let option = shallow(
<OptionRender {...mockReactSelectOptionProps({ type: 'view', value: 'test', label: 'test' })} />
);

expect(option.find(ListIcon).type).toBeDefined();
option = shallow(
<OptionRender
{...mockReactSelectOptionProps({ type: 'visualization', value: 'test', label: '' })}
/>
);
expect(option.find(BubblesIcon).type).toBeDefined();
});

it('should handle perspective change correctly', () => {
const onChange = jest.fn();
const instance = shallow(
<PerspectiveSelect onChange={onChange} view="visualizations" visualization="coverage" />
).instance() as PerspectiveSelect;
const instance = shallowRender({ onChange }).instance();
instance.handleChange({ label: 'overall', value: 'overall', type: 'view' });
instance.handleChange({ label: 'leak', value: 'leak', type: 'view' });
instance.handleChange({ label: 'coverage', value: 'coverage', type: 'visualization' });
expect(onChange.mock.calls).toMatchSnapshot();
});

function shallowRender(overrides: Partial<PerspectiveSelect['props']> = {}) {
return shallow<PerspectiveSelect>(
<PerspectiveSelect onChange={jest.fn()} view="visualizations" {...overrides} />
);
}

+ 0
- 80
server/sonar-web/src/main/js/apps/projects/components/__tests__/PerspectiveSelectOption-test.tsx View File

@@ -1,80 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2021 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import PerspectiveSelectOption from '../PerspectiveSelectOption';

it('should render correctly for a view', () => {
expect(
shallow(
<PerspectiveSelectOption
onFocus={jest.fn()}
onSelect={jest.fn()}
option={{ value: 'overall', type: 'view', label: 'Overall' }}>
Overall
</PerspectiveSelectOption>
)
).toMatchSnapshot();
});

it('should render correctly for a visualization', () => {
expect(
shallow(
<PerspectiveSelectOption
onFocus={jest.fn()}
onSelect={jest.fn()}
option={{ value: 'coverage', type: 'visualization', label: 'Coverage' }}>
Coverage
</PerspectiveSelectOption>
)
).toMatchSnapshot();
});

it('selects option', () => {
const onSelect = jest.fn();
const option = { value: 'coverage', type: 'visualization', label: 'Coverage' };
const wrapper = shallow(
<PerspectiveSelectOption onFocus={jest.fn()} onSelect={onSelect} option={option} />
);
const event = { stopPropagation() {}, preventDefault() {} };
wrapper.simulate('mousedown', event);
expect(onSelect).toBeCalledWith(option, event);
});

it('focuses option', () => {
const onFocus = jest.fn();
const option = { value: 'coverage', type: 'visualization', label: 'Coverage' };
const wrapper = shallow(
<PerspectiveSelectOption onFocus={onFocus} onSelect={jest.fn()} option={option} />
);
const event = { stopPropagation() {}, preventDefault() {} };

wrapper.simulate('mouseenter', event);
expect(onFocus).toBeCalledWith(option, event);

onFocus.mockClear();
wrapper.simulate('mousemove', event);
expect(onFocus).toBeCalledWith(option, event);

onFocus.mockClear();
wrapper.setProps({ isFocused: true });
wrapper.simulate('mousemove', event);
expect(onFocus).not.toBeCalled();
});

+ 41
- 37
server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelect-test.tsx View File

@@ -19,43 +19,46 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { GroupTypeBase } from 'react-select';
import { mockReactSelectOptionProps } from '../../../../helpers/mocks/react-select';
import { click } from '../../../../helpers/testUtils';
import ProjectsSortingSelect from '../ProjectsSortingSelect';
import ProjectsSortingSelect, { Option } from '../ProjectsSortingSelect';

it('should render correctly for overall view', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should render correctly for leak view', () => {
expect(
shallow(
<ProjectsSortingSelect
defaultOption="name"
onChange={jest.fn()}
selectedSort="name"
view="overall"
/>
)
shallowRender({ defaultOption: 'analysis_date', selectedSort: 'new_coverage', view: 'leak' })
).toMatchSnapshot();
});

it('should render correctly for leak view', () => {
it('should handle the descending sort direction', () => {
expect(shallowRender({ selectedSort: '-vulnerability' })).toMatchSnapshot();
});

it('should render option correctly', () => {
const wrapper = shallowRender();
const SortOption = wrapper.instance().projectsSortingSelectOption;
expect(
shallow(
<ProjectsSortingSelect
defaultOption="analysis_date"
onChange={jest.fn()}
selectedSort="new_coverage"
view="leak"
<SortOption
{...mockReactSelectOptionProps<Option, false, GroupTypeBase<Option>>({
label: 'foo',
value: 'foo',
short: 'fo'
})}
/>
)
).toMatchSnapshot();
});

it('should handle the descending sort direction', () => {
expect(
shallow(
<ProjectsSortingSelect
defaultOption="name"
onChange={jest.fn()}
selectedSort="-vulnerability"
view="overall"
<SortOption
{...mockReactSelectOptionProps<Option, false, GroupTypeBase<Option>>({
label: 'foo',
value: 'foo'
})}
/>
)
).toMatchSnapshot();
@@ -63,28 +66,29 @@ it('should handle the descending sort direction', () => {

it('changes sorting', () => {
const onChange = jest.fn();
const instance = shallow(
<ProjectsSortingSelect
defaultOption="name"
onChange={onChange}
selectedSort="-vulnerabilities"
view="overall"
/>
).instance() as ProjectsSortingSelect;
const instance = shallowRender({
selectedSort: '-vulnerability',
onChange
}).instance() as ProjectsSortingSelect;
instance.handleSortChange({ label: 'size', value: 'size' });
expect(onChange).toBeCalledWith('size', true);
});

it('reverses sorting', () => {
const onChange = jest.fn();
const wrapper = shallow(
const wrapper = shallowRender({ selectedSort: '-size', onChange });
click(wrapper.find('ButtonIcon'));
expect(onChange).toBeCalledWith('size', false);
});

function shallowRender(overrides: Partial<ProjectsSortingSelect['props']> = {}) {
return shallow<ProjectsSortingSelect>(
<ProjectsSortingSelect
defaultOption="name"
onChange={onChange}
selectedSort="-size"
onChange={jest.fn()}
selectedSort="name"
view="overall"
{...overrides}
/>
);
click(wrapper.find('ButtonIcon'));
expect(onChange).toBeCalledWith('size', false);
});
}

+ 0
- 80
server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelectOption-test.tsx View File

@@ -1,80 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2021 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import ProjectsSortingSelectOption from '../ProjectsSortingSelectOption';

it('renders', () => {
expect(
shallow(
<ProjectsSortingSelectOption
onFocus={jest.fn()}
onSelect={jest.fn()}
option={{ label: 'Size', value: 'size' }}>
Size
</ProjectsSortingSelectOption>
)
).toMatchSnapshot();
});

it('renders short', () => {
expect(
shallow(
<ProjectsSortingSelectOption
onFocus={jest.fn()}
onSelect={jest.fn()}
option={{ label: 'Size', short: 'Short', value: 'size' }}>
Size
</ProjectsSortingSelectOption>
)
).toMatchSnapshot();
});

it('selects option', () => {
const onSelect = jest.fn();
const option = { value: 'coverage', type: 'visualization', label: 'Coverage' };
const wrapper = shallow(
<ProjectsSortingSelectOption onFocus={jest.fn()} onSelect={onSelect} option={option} />
);
const event = { stopPropagation() {}, preventDefault() {} };
wrapper.simulate('mousedown', event);
expect(onSelect).toBeCalledWith(option, event);
});

it('focuses option', () => {
const onFocus = jest.fn();
const option = { value: 'coverage', type: 'visualization', label: 'Coverage' };
const wrapper = shallow(
<ProjectsSortingSelectOption onFocus={onFocus} onSelect={jest.fn()} option={option} />
);
const event = { stopPropagation() {}, preventDefault() {} };

wrapper.simulate('mouseenter', event);
expect(onFocus).toBeCalledWith(option, event);

onFocus.mockClear();
wrapper.simulate('mousemove', event);
expect(onFocus).toBeCalledWith(option, event);

onFocus.mockClear();
wrapper.setProps({ isFocused: true });
wrapper.simulate('mousemove', event);
expect(onFocus).not.toBeCalled();
});

+ 38
- 12
server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.tsx.snap View File

@@ -23,15 +23,23 @@ Array [

exports[`should render correctly 1`] = `
<div>
<label>
<label
id="aria-projects-perspective"
>
projects.perspective
:
</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-perspective"
className="little-spacer-left input-medium it__projects-perspective-select"
components={
Object {
"Option": [Function],
}
}
isClearable={false}
isSearchable={false}
onChange={[Function]}
optionComponent={[Function]}
options={
Array [
Object {
@@ -76,23 +84,36 @@ exports[`should render correctly 1`] = `
},
]
}
searchable={false}
value="overall"
value={
Object {
"label": "projects.view.overall",
"type": "view",
"value": "overall",
}
}
/>
</div>
`;

exports[`should render with coverage selected 1`] = `
<div>
<label>
<label
id="aria-projects-perspective"
>
projects.perspective
:
</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-perspective"
className="little-spacer-left input-medium it__projects-perspective-select"
components={
Object {
"Option": [Function],
}
}
isClearable={false}
isSearchable={false}
onChange={[Function]}
optionComponent={[Function]}
options={
Array [
Object {
@@ -137,8 +158,13 @@ exports[`should render with coverage selected 1`] = `
},
]
}
searchable={false}
value="coverage"
value={
Object {
"label": "projects.visualization.coverage",
"type": "visualization",
"value": "coverage",
}
}
/>
</div>
`;

+ 0
- 33
server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelectOption-test.tsx.snap View File

@@ -1,33 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for a view 1`] = `
<div
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseMove={[Function]}
title="Overall"
>
<div>
<ListIcon
className="little-spacer-right"
/>
Overall
</div>
</div>
`;

exports[`should render correctly for a visualization 1`] = `
<div
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseMove={[Function]}
title="Coverage"
>
<div>
<BubblesIcon
className="little-spacer-right"
/>
Coverage
</div>
</div>
`;

+ 107
- 45
server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelect-test.tsx.snap View File

@@ -2,71 +2,78 @@

exports[`should handle the descending sort direction 1`] = `
<div>
<label>
<label
id="aria-projects-sort"
>
projects.sort_by
:
</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-sort"
className="little-spacer-left input-medium it__projects-sort-select"
components={
Object {
"Option": [Function],
}
}
isClearable={false}
isSearchable={false}
onChange={[Function]}
optionComponent={[Function]}
options={
Array [
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.name",
"value": "name",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.analysis_date",
"value": "analysis_date",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.reliability",
"value": "reliability",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.security",
"value": "security",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.security_review",
"value": "security_review",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.maintainability",
"value": "maintainability",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.coverage",
"value": "coverage",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.duplications",
"value": "duplications",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.size",
"value": "size",
},
]
}
searchable={false}
value="vulnerability"
/>
<Tooltip
overlay="projects.sort_descending"
>
<ButtonIcon
aria-label="projects.sort_descending"
className="js-projects-sorting-invert spacer-left"
color="#999"
onClick={[Function]}
@@ -81,71 +88,85 @@ exports[`should handle the descending sort direction 1`] = `

exports[`should render correctly for leak view 1`] = `
<div>
<label>
<label
id="aria-projects-sort"
>
projects.sort_by
:
</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-sort"
className="little-spacer-left input-medium it__projects-sort-select"
components={
Object {
"Option": [Function],
}
}
isClearable={false}
isSearchable={false}
onChange={[Function]}
optionComponent={[Function]}
options={
Array [
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.analysis_date",
"value": "analysis_date",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.name",
"value": "name",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_reliability",
"value": "new_reliability",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_security",
"value": "new_security",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_security_review",
"value": "new_security_review",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_maintainability",
"value": "new_maintainability",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_coverage",
"value": "new_coverage",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_duplications",
"value": "new_duplications",
},
Object {
"class": "projects-leak-sorting-option",
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_lines",
"value": "new_lines",
},
]
}
searchable={false}
value="new_coverage"
value={
Object {
"className": "projects-leak-sorting-option",
"label": "projects.sorting.new_coverage",
"value": "new_coverage",
}
}
/>
<Tooltip
overlay="projects.sort_ascending"
>
<ButtonIcon
aria-label="projects.sort_ascending"
className="js-projects-sorting-invert spacer-left"
color="#999"
onClick={[Function]}
@@ -160,71 +181,85 @@ exports[`should render correctly for leak view 1`] = `

exports[`should render correctly for overall view 1`] = `
<div>
<label>
<label
id="aria-projects-sort"
>
projects.sort_by
:
</label>
<Select
className="little-spacer-left input-medium"
clearable={false}
aria-labelledby="aria-projects-sort"
className="little-spacer-left input-medium it__projects-sort-select"
components={
Object {
"Option": [Function],
}
}
isClearable={false}
isSearchable={false}
onChange={[Function]}
optionComponent={[Function]}
options={
Array [
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.name",
"value": "name",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.analysis_date",
"value": "analysis_date",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.reliability",
"value": "reliability",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.security",
"value": "security",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.security_review",
"value": "security_review",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.maintainability",
"value": "maintainability",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.coverage",
"value": "coverage",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.duplications",
"value": "duplications",
},
Object {
"class": undefined,
"className": undefined,
"label": "projects.sorting.size",
"value": "size",
},
]
}
searchable={false}
value="name"
value={
Object {
"className": undefined,
"label": "projects.sorting.name",
"value": "name",
}
}
/>
<Tooltip
overlay="projects.sort_ascending"
>
<ButtonIcon
aria-label="projects.sort_ascending"
className="js-projects-sorting-invert spacer-left"
color="#999"
onClick={[Function]}
@@ -236,3 +271,30 @@ exports[`should render correctly for overall view 1`] = `
</Tooltip>
</div>
`;

exports[`should render option correctly 1`] = `
<Option
className="it__project-sort-option-foo undefined"
data={
Object {
"label": "foo",
"short": "fo",
"value": "foo",
}
}
>
fo
</Option>
`;

exports[`should render option correctly 2`] = `
<Option
className="it__project-sort-option-foo undefined"
data={
Object {
"label": "foo",
"value": "foo",
}
}
/>
`;

+ 0
- 25
server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelectOption-test.tsx.snap View File

@@ -1,25 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders 1`] = `
<div
className=""
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseMove={[Function]}
title="Size"
>
Size
</div>
`;

exports[`renders short 1`] = `
<div
className=""
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseMove={[Function]}
title="Size"
>
Short
</div>
`;

+ 2
- 2
server/sonar-web/src/main/js/apps/projects/filters/SearchableFilterFooter.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { translate } from '../../../helpers/l10n';

interface Props {
@@ -41,7 +41,7 @@ export default class SearchableFilterFooter extends React.PureComponent<Props> {
render() {
return (
<div className="search-navigator-facet-footer projects-facet-footer">
<Select
<SelectLegacy
className="input-super-large"
clearable={false}
isLoading={this.props.isLoading}

+ 3
- 2
server/sonar-web/src/main/js/apps/projects/filters/__tests__/SearchableFilterFooter-test.tsx View File

@@ -19,6 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import SearchableFilterFooter from '../SearchableFilterFooter';

const options = [
@@ -36,7 +37,7 @@ it('should render items without the ones in the facet', () => {
query={{ languages: ['java'] }}
/>
);
expect(wrapper.find('Select').prop('options')).toMatchSnapshot();
expect(wrapper.find(SelectLegacy).prop('options')).toMatchSnapshot();
});

it('should properly handle a change of the facet value', () => {
@@ -49,6 +50,6 @@ it('should properly handle a change of the facet value', () => {
query={{ languages: ['java'] }}
/>
);
(wrapper.find('Select').prop('onChange') as Function)({ value: 'js' });
(wrapper.find(SelectLegacy).prop('onChange') as Function)({ value: 'js' });
expect(onQueryChange).toBeCalledWith({ languages: 'java,js' });
});

+ 2
- 2
server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx View File

@@ -21,7 +21,7 @@ import * as React from 'react';
import { bulkApplyTemplate, getPermissionTemplates } from '../../api/permissions';
import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons';
import Modal from '../../components/controls/Modal';
import Select from '../../components/controls/Select';
import SelectLegacy from '../../components/controls/SelectLegacy';
import { Alert } from '../../components/ui/Alert';
import MandatoryFieldMarker from '../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../components/ui/MandatoryFieldsExplanation';
@@ -137,7 +137,7 @@ export default class BulkApplyTemplateModal extends React.PureComponent<Props, S
{translate('template')}
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
disabled={this.state.submitting}
onChange={this.handlePermissionTemplateChange}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx View File

@@ -25,7 +25,7 @@ import Checkbox from '../../components/controls/Checkbox';
import DateInput from '../../components/controls/DateInput';
import HelpTooltip from '../../components/controls/HelpTooltip';
import SearchBox from '../../components/controls/SearchBox';
import Select from '../../components/controls/Select';
import SelectLegacy from '../../components/controls/SelectLegacy';
import QualifierIcon from '../../components/icons/QualifierIcon';
import { translate } from '../../helpers/l10n';
import BulkApplyTemplateModal from './BulkApplyTemplateModal';
@@ -136,7 +136,7 @@ export default class Search extends React.PureComponent<Props, State> {
}
return (
<td className="thin nowrap text-middle">
<Select
<SelectLegacy
className="input-medium"
clearable={false}
disabled={!this.props.ready}
@@ -155,7 +155,7 @@ export default class Search extends React.PureComponent<Props, State> {
renderVisibilityFilter = () => {
return (
<td className="thin nowrap text-middle">
<Select
<SelectLegacy
className="input-small"
clearable={false}
disabled={!this.props.ready}

+ 3
- 1
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx View File

@@ -43,7 +43,9 @@ it('render qualifiers filter', () => {
it('updates qualifier', () => {
const onQualifierChanged = jest.fn();
const wrapper = shallowRender({ onQualifierChanged, topLevelQualifiers: ['TRK', 'VW', 'APP'] });
wrapper.find('Select[name="projects-qualifier"]').prop<Function>('onChange')({ value: 'VW' });
wrapper.find('SelectLegacy[name="projects-qualifier"]').prop<Function>('onChange')({
value: 'VW'
});
expect(onQualifierChanged).toBeCalledWith('VW');
});


+ 4
- 4
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap View File

@@ -63,7 +63,7 @@ exports[`bulk applies template to all results 2`] = `
template
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
onChange={[Function]}
@@ -132,7 +132,7 @@ exports[`bulk applies template to all results 3`] = `
template
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
disabled={true}
onChange={[Function]}
@@ -270,7 +270,7 @@ exports[`bulk applies template to selected results 2`] = `
template
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
disabled={false}
onChange={[Function]}
@@ -339,7 +339,7 @@ exports[`bulk applies template to selected results 3`] = `
template
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
disabled={true}
onChange={[Function]}

+ 3
- 3
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap View File

@@ -50,7 +50,7 @@ exports[`render qualifiers filter 1`] = `
<td
className="thin nowrap text-middle"
>
<Select
<SelectLegacy
className="input-medium"
clearable={false}
disabled={false}
@@ -91,7 +91,7 @@ exports[`render qualifiers filter 1`] = `
<td
className="thin nowrap text-middle"
>
<Select
<SelectLegacy
className="input-small"
clearable={false}
disabled={false}
@@ -205,7 +205,7 @@ exports[`renders 1`] = `
<td
className="thin nowrap text-middle"
>
<Select
<SelectLegacy
className="input-small"
clearable={false}
disabled={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { translate } from '../../../helpers/l10n';
import { getPossibleOperators } from '../utils';

@@ -49,7 +49,7 @@ export default class ConditionOperator extends React.PureComponent<Props> {
});

return (
<Select
<SelectLegacy
autoFocus={true}
className="input-medium"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx View File

@@ -19,7 +19,7 @@
*/
import { sortBy } from 'lodash';
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { getLocalizedMetricDomain, translate } from '../../../helpers/l10n';
import { getLocalizedMetricNameNoDiffMetric } from '../utils';

@@ -73,7 +73,7 @@ export default class MetricSelect extends React.PureComponent<Props> {
});

return (
<Select
<SelectLegacy
className="text-middle quality-gate-metric-select"
id="condition-metric"
onChange={this.handleChange}

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx View File

@@ -20,7 +20,7 @@
import * as React from 'react';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import GroupIcon from '../../../components/icons/GroupIcon';
import Avatar from '../../../components/ui/Avatar';
import { translate, translateWithParameters } from '../../../helpers/l10n';
@@ -59,7 +59,7 @@ export default function QualityGatePermissionsAddModalRenderer(
<div className="modal-body">
<div className="modal-field">
<label>{translate('quality_gates.permissions.search')}</label>
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';

interface Props {
name: string;
@@ -51,7 +51,7 @@ export default class ThresholdInput extends React.PureComponent<Props> {
];

return (
<Select
<SelectLegacy
className="input-tiny text-middle"
clearable={true}
id="condition-threshold"

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { mockUserBase } from '../../../../helpers/mocks/users';
import QualityGatePermissionsAddModalRenderer, {
QualityGatePermissionsAddModalRendererProps
@@ -40,7 +40,7 @@ it('should render correctly', () => {
it('should render options correctly', () => {
const wrapper = shallowRender();

const { optionRenderer = () => null } = wrapper.find(Select).props();
const { optionRenderer = () => null } = wrapper.find(SelectLegacy).props();

expect(optionRenderer({ avatar: 'A', name: 'name', login: 'login' })).toMatchSnapshot('user');
expect(optionRenderer({ name: 'group name' })).toMatchSnapshot('group');

+ 4
- 3
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ThresholdInput-test.tsx View File

@@ -19,6 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { change } from '../../../../helpers/testUtils';
import ThresholdInput from '../ThresholdInput';

@@ -48,7 +49,7 @@ describe('on ratings', () => {
it('should render Select', () => {
const select = shallow(
<ThresholdInput metric={metric} name="foo" onChange={jest.fn()} value="2" />
).find('Select');
).find(SelectLegacy);
expect(select.length).toEqual(1);
expect(select.prop('value')).toEqual('2');
});
@@ -57,7 +58,7 @@ describe('on ratings', () => {
const onChange = jest.fn();
const select = shallow(
<ThresholdInput metric={metric} name="foo" onChange={onChange} value="2" />
).find('Select');
).find(SelectLegacy);
(select.prop('onChange') as Function)({ label: 'D', value: '4' });
expect(onChange).toBeCalledWith('4');
});
@@ -66,7 +67,7 @@ describe('on ratings', () => {
const onChange = jest.fn();
const select = shallow(
<ThresholdInput metric={metric} name="foo" onChange={onChange} value="2" />
).find('Select');
).find(SelectLegacy);
(select.prop('onChange') as Function)(null);
expect(onChange).toBeCalledWith('');
});

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionOperator-test.tsx.snap View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Select
<SelectLegacy
autoFocus={true}
className="input-medium"
clearable={false}

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/MetricSelect-test.tsx.snap View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Select
<SelectLegacy
className="text-middle quality-gate-metric-select"
id="condition-metric"
onChange={[Function]}

+ 5
- 5
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap View File

@@ -24,7 +24,7 @@ exports[`should render correctly: default 1`] = `
<label>
quality_gates.permissions.search
</label>
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}
@@ -83,7 +83,7 @@ exports[`should render correctly: query and results 1`] = `
<label>
quality_gates.permissions.search
</label>
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}
@@ -153,7 +153,7 @@ exports[`should render correctly: selection 1`] = `
<label>
quality_gates.permissions.search
</label>
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}
@@ -217,7 +217,7 @@ exports[`should render correctly: short query 1`] = `
<label>
quality_gates.permissions.search
</label>
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}
@@ -276,7 +276,7 @@ exports[`should render correctly: submitting 1`] = `
<label>
quality_gates.permissions.search
</label>
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import Tooltip from '../../../components/controls/Tooltip';
import { translate } from '../../../helpers/l10n';
import { Profile } from '../types';
@@ -57,7 +57,7 @@ export default class ComparisonForm extends React.PureComponent<Props> {
return (
<div className="display-inline-block">
<label className="spacer-right">{translate('quality_profiles.compare_with')}</label>
<Select
<SelectLegacy
className="input-large"
clearable={false}
onChange={this.handleChange}

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { mockQualityProfile } from '../../../../helpers/testMocks';
import ComparisonForm from '../ComparisonForm';

@@ -40,7 +40,7 @@ it('should render Select with right options', () => {
profiles={profiles}
withKey="another"
/>
).find(Select);
).find(SelectLegacy);
expect(output.props().valueRenderer!(profileDefault)).toMatchSnapshot('Render default for value');
expect(output.props().valueRenderer!(profile)).toMatchSnapshot('Render for value');


+ 2
- 2
server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.tsx View File

@@ -22,7 +22,7 @@ import * as React from 'react';
import { changeProfileParent } from '../../../api/quality-profiles';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
import { translate } from '../../../helpers/l10n';
@@ -108,7 +108,7 @@ export default class ChangeParentForm extends React.PureComponent<Props, State>
{translate('quality_profiles.parent')}
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
id="change-profile-parent"
name="parentKey"

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-profiles/details/ProfilePermissionsFormSelect.tsx View File

@@ -19,7 +19,7 @@
*/
import { debounce, identity } from 'lodash';
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import GroupIcon from '../../../components/icons/GroupIcon';
import Avatar from '../../../components/ui/Avatar';
import { translate, translateWithParameters } from '../../../helpers/l10n';
@@ -91,7 +91,7 @@ export default class ProfilePermissionsFormSelect extends React.PureComponent<Pr
const options = this.state.searchResults.map(r => ({ ...r, value: getStringValue(r) }));

return (
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ChangeParentForm-test.tsx.snap View File

@@ -32,7 +32,7 @@ exports[`should render correctly 1`] = `
quality_profiles.parent
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
id="change-profile-parent"
name="parentKey"

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfilePermissionsFormSelect-test.tsx.snap View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders 1`] = `
<Select
<SelectLegacy
autoFocus={true}
className="Select-big"
clearable={false}

+ 3
- 3
server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx View File

@@ -26,7 +26,7 @@ import {
} from '../../../api/quality-profiles';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { Location } from '../../../components/hoc/withRouter';
import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
@@ -174,7 +174,7 @@ export default class CreateProfileForm extends React.PureComponent<Props, State>
{translate('language')}
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
id="create-profile-language"
name="language"
@@ -191,7 +191,7 @@ export default class CreateProfileForm extends React.PureComponent<Props, State>
<label htmlFor="create-profile-parent">
{translate('quality_profiles.parent')}
</label>
<Select
<SelectLegacy
clearable={true}
id="create-profile-parent"
name="parentKey"

+ 2
- 2
server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { Router, withRouter } from '../../../components/hoc/withRouter';
import { translate } from '../../../helpers/l10n';
import { getProfilesForLanguagePath, PROFILE_PATH } from '../utils';
@@ -52,7 +52,7 @@ export class ProfilesListHeader extends React.PureComponent<Props> {
return (
<header className="quality-profiles-list-header clearfix">
<span className="spacer-right">{translate('quality_profiles.filter_by')}:</span>
<Select
<SelectLegacy
className="input-medium"
clearable={true}
onChange={this.handleChange}

+ 4
- 4
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/CreateProfileForm-test.tsx.snap View File

@@ -53,7 +53,7 @@ exports[`should render correctly: default 1`] = `
language
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
id="create-profile-language"
name="language"
@@ -81,7 +81,7 @@ exports[`should render correctly: default 1`] = `
>
quality_profiles.parent
</label>
<Select
<SelectLegacy
clearable={true}
id="create-profile-parent"
name="parentKey"
@@ -180,7 +180,7 @@ exports[`should render correctly: with query filter 1`] = `
language
<MandatoryFieldMarker />
</label>
<Select
<SelectLegacy
clearable={false}
id="create-profile-language"
name="language"
@@ -208,7 +208,7 @@ exports[`should render correctly: with query filter 1`] = `
>
quality_profiles.parent
</label>
<Select
<SelectLegacy
clearable={true}
id="create-profile-parent"
name="parentKey"

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/ProfilesListHeader-test.tsx.snap View File

@@ -10,7 +10,7 @@ exports[`should render correctly 1`] = `
quality_profiles.filter_by
:
</span>
<Select
<SelectLegacy
className="input-medium"
clearable={true}
onChange={[Function]}

+ 3
- 3
server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx View File

@@ -20,7 +20,7 @@
import * as React from 'react';
import HelpTooltip from '../../../components/controls/HelpTooltip';
import RadioToggle from '../../../components/controls/RadioToggle';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import Measure from '../../../components/measure/Measure';
import CoverageRating from '../../../components/ui/CoverageRating';
@@ -107,7 +107,7 @@ export function FilterBar(props: FilterBarProps) {
)}

<span className="spacer-right">{translate('status')}</span>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={(option: { value: HotspotStatusFilter }) =>
@@ -119,7 +119,7 @@ export function FilterBar(props: FilterBarProps) {
/>

{onBranch && (
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={(option: { value: boolean }) =>

+ 3
- 3
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx View File

@@ -20,7 +20,7 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import RadioToggle from '../../../../components/controls/RadioToggle';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
@@ -60,7 +60,7 @@ it('should trigger onChange for status', () => {
const wrapper = shallowRender({ onChangeFilters });

const { onChange } = wrapper
.find(Select)
.find(SelectLegacy)
.at(0)
.props();

@@ -83,7 +83,7 @@ it('should trigger onChange for leak period', () => {
const wrapper = shallowRender({ onChangeFilters });

const { onChange } = wrapper
.find(Select)
.find(SelectLegacy)
.at(1)
.props();


+ 9
- 9
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap View File

@@ -49,7 +49,7 @@ exports[`should render correctly: anonymous 1`] = `
>
status
</span>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -72,7 +72,7 @@ exports[`should render correctly: anonymous 1`] = `
searchable={false}
value="TO_REVIEW"
/>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -165,7 +165,7 @@ exports[`should render correctly: logged-in 1`] = `
>
status
</span>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -188,7 +188,7 @@ exports[`should render correctly: logged-in 1`] = `
searchable={false}
value="TO_REVIEW"
/>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -281,7 +281,7 @@ exports[`should render correctly: non-project 1`] = `
>
status
</span>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -304,7 +304,7 @@ exports[`should render correctly: non-project 1`] = `
searchable={false}
value="TO_REVIEW"
/>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -356,7 +356,7 @@ exports[`should render correctly: on Pull request 1`] = `
>
status
</span>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -434,7 +434,7 @@ exports[`should render correctly: with hotspots reviewed measure 1`] = `
>
status
</span>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}
@@ -457,7 +457,7 @@ exports[`should render correctly: with hotspots reviewed measure 1`] = `
searchable={false}
value="TO_REVIEW"
/>
<Select
<SelectLegacy
className="input-medium big-spacer-right"
clearable={false}
onChange={[Function]}

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/Languages.tsx View File

@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import { connect } from 'react-redux';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
import { translate } from '../../../helpers/l10n';
import { getSettingsAppAllCategories, Store } from '../../../store/rootReducer';
@@ -56,7 +56,7 @@ export function Languages(props: LanguagesProps) {
<>
<h2 className="settings-sub-category-name">{translate('property.category.languages')}</h2>
<div data-test="language-select">
<Select
<SelectLegacy
className="input-large"
onChange={handleOnChange}
options={availableLanguages}

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/__tests__/Languages-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockLocation, mockRouter } from '../../../../helpers/testMocks';
import CategoryDefinitionsList from '../CategoryDefinitionsList';
@@ -41,7 +41,7 @@ it('should correctly handle a change of the selected language', () => {
const wrapper = shallowRender({ router });
expect(wrapper.find(CategoryDefinitionsList).props().category).toBe('java');

const { onChange } = wrapper.find(Select).props();
const { onChange } = wrapper.find(SelectLegacy).props();

onChange!({ label: '', originalValue: 'CoBoL', value: 'cobol' });
expect(push).toHaveBeenCalledWith(expect.objectContaining({ query: { category: 'CoBoL' } }));

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/__tests__/__snapshots__/Languages-test.tsx.snap View File

@@ -10,7 +10,7 @@ exports[`should render correctly 1`] = `
<div
data-test="language-select"
>
<Select
<SelectLegacy
className="input-large"
onChange={[Function]}
options={
@@ -56,7 +56,7 @@ exports[`should render correctly with an unknow language 1`] = `
<div
data-test="language-select"
>
<Select
<SelectLegacy
className="input-large"
onChange={[Function]}
options={

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { SettingCategoryDefinition } from '../../../../types/settings';
import { DefaultSpecializedInputProps } from '../../utils';

@@ -36,7 +36,7 @@ export default class InputForSingleSelectList extends React.PureComponent<Props>
}));

return (
<Select
<SelectLegacy
className="settings-large-input"
clearable={false}
name={this.props.name}

+ 3
- 2
server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/InputForSingleSelectList-test.tsx View File

@@ -19,13 +19,14 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import SelectLegacy from '../../../../../components/controls/SelectLegacy';
import { mockSetting } from '../../../../../helpers/mocks/settings';
import { DefaultSpecializedInputProps } from '../../../utils';
import InputForSingleSelectList from '../InputForSingleSelectList';

it('should render Select', () => {
const onChange = jest.fn();
const select = shallowRender({ onChange }).find('Select');
const select = shallowRender({ onChange }).find(SelectLegacy);
expect(select.length).toBe(1);
expect(select.prop('name')).toBe('foo');
expect(select.prop('value')).toBe('bar');
@@ -39,7 +40,7 @@ it('should render Select', () => {

it('should call onChange', () => {
const onChange = jest.fn();
const select = shallowRender({ onChange }).find('Select');
const select = shallowRender({ onChange }).find(SelectLegacy);
expect(select.length).toBe(1);
expect(select.prop('onChange')).toBeDefined();


+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx View File

@@ -21,7 +21,7 @@ import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import { Button, SubmitButton } from '../../../../components/controls/buttons';
import Select from '../../../../components/controls/Select';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import AlertSuccessIcon from '../../../../components/icons/AlertSuccessIcon';
import { Alert } from '../../../../components/ui/Alert';
import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
@@ -143,7 +143,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
</div>
</div>
<div className="settings-definition-right">
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import Select from '../../../../../components/controls/Select';
import SelectLegacy from '../../../../../components/controls/SelectLegacy';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
import {
AlmKeys,
@@ -129,7 +129,7 @@ it('should render select options correctly', async () => {

await waitAndUpdate(wrapper);

const { optionRenderer } = wrapper.find(Select).props();
const { optionRenderer } = wrapper.find(SelectLegacy).props();

expect(optionRenderer!(instances[0])).toMatchSnapshot();


+ 6
- 6
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap View File

@@ -129,7 +129,7 @@ exports[`should render correctly: when there are configuration errors (admin use
<div
className="settings-definition-right"
>
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}
@@ -331,7 +331,7 @@ exports[`should render correctly: when there are configuration errors (admin use
<div
className="settings-definition-right"
>
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}
@@ -473,7 +473,7 @@ exports[`should render correctly: when there are configuration errors (non-admin
<div
className="settings-definition-right"
>
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}
@@ -618,7 +618,7 @@ exports[`should render correctly: with a single ALM instance 1`] = `
<div
className="settings-definition-right"
>
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}
@@ -700,7 +700,7 @@ exports[`should render correctly: with a valid and saved form 1`] = `
<div
className="settings-definition-right"
>
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}
@@ -859,7 +859,7 @@ exports[`should render correctly: with an empty form 1`] = `
<div
className="settings-definition-right"
>
<Select
<SelectLegacy
autosize={true}
className="abs-width-400 big-spacer-top"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.tsx View File

@@ -19,7 +19,7 @@
*/
import { debounce } from 'lodash';
import * as React from 'react';
import Select from '../../../components/controls/Select';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import Avatar from '../../../components/ui/Avatar';
import { translate, translateWithParameters } from '../../../helpers/l10n';

@@ -110,7 +110,7 @@ export default class UsersSelectSearch extends React.PureComponent<Props, State>
? translateWithParameters('select2.tooShort', 2)
: translate('no_results');
return (
<Select
<SelectLegacy
autoFocus={this.props.autoFocus}
className="Select-big"
clearable={false}

+ 2
- 2
server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearch-test.tsx.snap View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`UsersSelectSearch should render correctly 1`] = `
<Select
<SelectLegacy
className="Select-big"
clearable={false}
filterOptions={[Function]}
@@ -42,7 +42,7 @@ Array [
`;

exports[`UsersSelectSearch should render correctly 3`] = `
<Select
<SelectLegacy
className="Select-big"
clearable={false}
filterOptions={[Function]}

+ 2
- 2
server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx View File

@@ -19,9 +19,9 @@
*/
import classNames from 'classnames';
import * as React from 'react';
import Select from '../../components/controls/Select';
import { translate } from '../../helpers/l10n';
import { GraphType } from '../../types/project-activity';
import SelectLegacy from '../controls/SelectLegacy';
import AddGraphMetric from './AddGraphMetric';
import './styles.css';
import { getGraphTypes, isCustomGraph } from './utils';
@@ -64,7 +64,7 @@ export default class GraphsHeader extends React.PureComponent<Props> {

return (
<div className={classNames(className, 'position-relative')}>
<Select
<SelectLegacy
className="pull-left input-medium"
clearable={false}
onChange={this.handleGraphChange}

+ 3
- 3
server/sonar-web/src/main/js/components/controls/DateInput.tsx View File

@@ -25,13 +25,13 @@ import { DayModifiers, Modifier, Modifiers } from 'react-day-picker';
import { InjectedIntlProps, injectIntl } from 'react-intl';
import { ButtonIcon, ClearButton } from '../../components/controls/buttons';
import OutsideClickHandler from '../../components/controls/OutsideClickHandler';
import Select from '../../components/controls/Select';
import CalendarIcon from '../../components/icons/CalendarIcon';
import ChevronLeftIcon from '../../components/icons/ChevronLeftIcon';
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 './styles.css';

const DayPicker = lazyLoadComponent(() => import('react-day-picker'), 'DayPicker');
@@ -172,7 +172,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
<ChevronLeftIcon />
</ButtonIcon>
<div className="date-input-calender-month">
<Select
<SelectLegacy
className="date-input-calender-month-select"
onChange={this.handleCurrentMonthChange}
options={months.map(month => ({
@@ -181,7 +181,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
}))}
value={this.state.currentMonth.getMonth()}
/>
<Select
<SelectLegacy
className="date-input-calender-month-select spacer-left"
onChange={this.handleCurrentYearChange}
options={years.map(year => ({ label: String(year), value: year }))}

+ 2
- 2
server/sonar-web/src/main/js/components/controls/SearchSelect.tsx View File

@@ -20,7 +20,7 @@
import { debounce } from 'lodash';
import * as React from 'react';
import { translate, translateWithParameters } from '../../helpers/l10n';
import Select, { Creatable } from './Select';
import SelectLegacy, { CreatableLegacy } from './SelectLegacy';

interface Props<T> {
autofocus?: boolean;
@@ -123,7 +123,7 @@ export default class SearchSelect<T extends { value: string }> extends React.Pur
handleFilterOption = () => true;

render() {
const Component = this.props.canCreate ? Creatable : Select;
const Component = this.props.canCreate ? CreatableLegacy : SelectLegacy;
return (
<Component
autoFocus={this.autofocus}

+ 127
- 31
server/sonar-web/src/main/js/components/controls/Select.tsx View File

@@ -17,43 +17,139 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import styled from '@emotion/styled';
import * as React from 'react';
import ReactSelectClass, {
ReactAsyncSelectProps,
ReactCreatableSelectProps,
ReactSelectProps
} from 'react-select';
import { lazyLoadComponent } from '../lazyLoadComponent';
import { ClearButton } from './buttons';
import './Select.css';
import ReactSelect, { GroupTypeBase, IndicatorProps, Props, StylesConfig } from 'react-select';
import { colors, others, sizes, zIndexes } from '../../app/theme';

const ReactSelectLib = import('react-select');
const ReactSelect = lazyLoadComponent(() => ReactSelectLib);
const ReactCreatable = lazyLoadComponent(() =>
ReactSelectLib.then(lib => ({ default: lib.Creatable }))
);
const ReactAsync = lazyLoadComponent(() => ReactSelectLib.then(lib => ({ default: lib.Async })));
const ArrowSpan = styled.span`
border-color: #999 transparent transparent;
border-style: solid;
border-width: 4px 4px 2px;
display: inline-block;
height: 0;
width: 0;
`;

function renderInput() {
return <ClearButton className="button-tiny spacer-left text-middle" iconProps={{ size: 12 }} />;
}

export interface WithInnerRef {
innerRef?: React.Ref<ReactSelectClass<unknown>>;
}
export default function Select<
Option,
IsMulti extends boolean = false,
Group extends GroupTypeBase<Option> = GroupTypeBase<Option>
>(props: Props<Option, IsMulti, Group>) {
function DropdownIndicator({ innerProps }: IndicatorProps<Option, IsMulti, Group>) {
return <ArrowSpan {...innerProps} />;
}

export default function Select({ innerRef, ...props }: WithInnerRef & ReactSelectProps) {
// hide the "x" icon when select is empty
const clearable = props.clearable ? Boolean(props.value) : false;
return (
<ReactSelect {...props} clearable={clearable} clearRenderer={renderInput} ref={innerRef} />
<ReactSelect
{...props}
styles={selectStyle<Option, IsMulti, Group>()}
components={{
...props.components,
DropdownIndicator
}}
/>
);
}

export function Creatable(props: ReactCreatableSelectProps) {
return <ReactCreatable {...props} clearRenderer={renderInput} />;
}

export function AsyncSelect(props: ReactAsyncSelectProps & WithInnerRef) {
return <ReactAsync {...props} />;
export function selectStyle<
Option,
IsMulti extends boolean,
Group extends GroupTypeBase<Option>
>(): StylesConfig<Option, IsMulti, Group> {
return {
container: () => ({
position: 'relative',
display: 'inline-block',
verticalAlign: 'middle',
fontSize: '12px',
textAlign: 'left'
}),
control: () => ({
position: 'relative',
display: 'table',
width: '100%',
height: `${sizes.controlHeight}`,
lineHeight: `calc(${sizes.controlHeight} - 2px)`,
border: `1px solid ${colors.gray80}`,
borderCollapse: 'separate',
borderRadius: '2px',
backgroundColor: '#fff',
boxSizing: 'border-box',
color: `${colors.baseFontColor}`,
cursor: 'default',
outline: 'none'
}),
singleValue: () => ({
bottom: 0,
left: 0,
lineHeight: '23px',
paddingLeft: '8px',
paddingRight: '24px',
position: 'absolute',
right: 0,
top: 0,
maxWidth: '100%',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}),
valueContainer: () => ({
bottom: 0,
left: 0,
lineHeight: '23px',
paddingLeft: '8px',
paddingRight: '24px',
position: 'absolute',
right: 0,
top: 0,
maxWidth: '100%',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}),
indicatorsContainer: () => ({
cursor: 'pointer',
display: 'table-cell',
position: 'relative',
textAlign: 'center',
verticalAlign: 'middle',
width: '20px',
paddingRight: '5px'
}),
menu: () => ({
borderBottomRightRadius: '4px',
borderBottomLeftRadius: '4px',
backgroundColor: '#fff',
border: '1px solid #ccc',
borderTopColor: `${colors.barBorderColor}`,
boxSizing: 'border-box',
marginTop: '-1px',
maxHeight: '200px',
position: 'absolute',
top: '100%',
width: '100%',
zIndex: `${zIndexes.dropdownMenuZIndex}`,
webkitOverflowScrolling: 'touch',
boxShadow: `${others.defaultShadow}`
}),
menuList: () => ({
maxHeight: '198px',
padding: '5px 0',
overflowY: 'auto'
}),
option: (_provided, state) => ({
display: 'block',
lineHeight: '20px',
padding: '0 8px',
boxSizing: 'border-box',
color: `${colors.baseFontColor}`,
backgroundColor: state.isFocused ? `${colors.barBackgroundColor}` : 'white',
fontSize: `${sizes.smallFontSize}`,
cursor: 'pointer',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
})
};
}

server/sonar-web/src/main/js/components/controls/Select.css → server/sonar-web/src/main/js/components/controls/SelectLegacy.css View File


+ 59
- 0
server/sonar-web/src/main/js/components/controls/SelectLegacy.tsx View File

@@ -0,0 +1,59 @@
/*
* SonarQube
* Copyright (C) 2009-2021 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import ReactSelectClass, {
ReactAsyncSelectProps,
ReactCreatableSelectProps,
ReactSelectProps
} from 'react-select-legacy';
import { lazyLoadComponent } from '../lazyLoadComponent';
import { ClearButton } from './buttons';
import './SelectLegacy.css';

const ReactSelectLib = import('react-select-legacy');
const ReactSelect = lazyLoadComponent(() => ReactSelectLib);
const ReactCreatable = lazyLoadComponent(() =>
ReactSelectLib.then(lib => ({ default: lib.Creatable }))
);
const ReactAsync = lazyLoadComponent(() => ReactSelectLib.then(lib => ({ default: lib.Async })));

function renderInput() {
return <ClearButton className="button-tiny spacer-left text-middle" iconProps={{ size: 12 }} />;
}

export interface WithInnerRef {
innerRef?: React.Ref<ReactSelectClass<unknown>>;
}

export default function SelectLegacy({ innerRef, ...props }: WithInnerRef & ReactSelectProps) {
// hide the "x" icon when select is empty
const clearable = props.clearable ? Boolean(props.value) : false;
return (
<ReactSelect {...props} clearable={clearable} clearRenderer={renderInput} ref={innerRef} />
);
}

export function CreatableLegacy(props: ReactCreatableSelectProps) {
return <ReactCreatable {...props} clearRenderer={renderInput} />;
}

export function AsyncSelectLegacy(props: ReactAsyncSelectProps & WithInnerRef) {
return <ReactAsync {...props} />;
}

+ 8
- 51
server/sonar-web/src/main/js/components/controls/__tests__/Select-test.tsx View File

@@ -20,62 +20,19 @@

import { shallow } from 'enzyme';
import * as React from 'react';
import { ReactAsyncSelectProps, ReactCreatableSelectProps, ReactSelectProps } from 'react-select';
import Select, { AsyncSelect, Creatable, WithInnerRef } from '../Select';
import { GroupTypeBase, Props } from 'react-select';
import Select from '../Select';

describe('Select', () => {
it('should render correctly', () => {
return new Promise<void>((resolve, reject) => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ clearable: true, value: undefined })).toMatchSnapshot(
'disable clear button if no value'
);

const clearRenderFn = shallowRender().props().clearRenderer;
if (!clearRenderFn) {
reject();
return;
}
expect(clearRenderFn()).toMatchSnapshot('clear button');

resolve();
});
});

function shallowRender(props: Partial<WithInnerRef & ReactSelectProps> = {}) {
return shallow<WithInnerRef & ReactSelectProps>(<Select value="foo" {...props} />);
}
});

describe('Creatable', () => {
it('should render correctly', () => {
return new Promise<void>((resolve, reject) => {
expect(shallowRender()).toMatchSnapshot('default');

const clearRenderFn = shallowRender().props().clearRenderer;
if (!clearRenderFn) {
reject();
return;
}
expect(clearRenderFn()).toMatchSnapshot('clear button');

resolve();
});
});

function shallowRender(props: Partial<ReactCreatableSelectProps> = {}) {
return shallow<ReactCreatableSelectProps>(<Creatable {...props} />);
}
});

describe('AsyncSelect', () => {
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
});

function shallowRender(props: Partial<WithInnerRef & ReactAsyncSelectProps> = {}) {
return shallow<WithInnerRef & ReactAsyncSelectProps>(
<AsyncSelect loadOptions={jest.fn()} {...props} />
);
function shallowRender<
Option,
IsMulti extends boolean = false,
Group extends GroupTypeBase<Option> = GroupTypeBase<Option>
>(props: Partial<Props<Option, IsMulti, Group>> = {}) {
return shallow<Props<Option, IsMulti, Group>>(<Select {...props} />);
}
});

+ 85
- 0
server/sonar-web/src/main/js/components/controls/__tests__/SelectLegacy-test.tsx View File

@@ -0,0 +1,85 @@
/*
* SonarQube
* Copyright (C) 2009-2021 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { shallow } from 'enzyme';
import * as React from 'react';
import {
ReactAsyncSelectProps,
ReactCreatableSelectProps,
ReactSelectProps
} from 'react-select-legacy';
import SelectLegacy, { AsyncSelectLegacy, CreatableLegacy, WithInnerRef } from '../SelectLegacy';

describe('Select', () => {
it('should render correctly', () => {
return new Promise<void>((resolve, reject) => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ clearable: true, value: undefined })).toMatchSnapshot(
'disable clear button if no value'
);

const clearRenderFn = shallowRender().props().clearRenderer;
if (!clearRenderFn) {
reject();
return;
}
expect(clearRenderFn()).toMatchSnapshot('clear button');

resolve();
});
});

function shallowRender(props: Partial<WithInnerRef & ReactSelectProps> = {}) {
return shallow<WithInnerRef & ReactSelectProps>(<SelectLegacy value="foo" {...props} />);
}
});

describe('Creatable', () => {
it('should render correctly', () => {
return new Promise<void>((resolve, reject) => {
expect(shallowRender()).toMatchSnapshot('default');

const clearRenderFn = shallowRender().props().clearRenderer;
if (!clearRenderFn) {
reject();
return;
}
expect(clearRenderFn()).toMatchSnapshot('clear button');

resolve();
});
});

function shallowRender(props: Partial<ReactCreatableSelectProps> = {}) {
return shallow<ReactCreatableSelectProps>(<CreatableLegacy {...props} />);
}
});

describe('AsyncSelect', () => {
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
});

function shallowRender(props: Partial<WithInnerRef & ReactAsyncSelectProps> = {}) {
return shallow<WithInnerRef & ReactAsyncSelectProps>(
<AsyncSelectLegacy loadOptions={jest.fn()} {...props} />
);
}
});

+ 2
- 2
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap View File

@@ -100,7 +100,7 @@ exports[`should render 3`] = `
<div
className="date-input-calender-month"
>
<Select
<SelectLegacy
className="date-input-calender-month-select"
onChange={[Function]}
options={
@@ -157,7 +157,7 @@ exports[`should render 3`] = `
}
value={0}
/>
<Select
<SelectLegacy
className="date-input-calender-month-select spacer-left"
onChange={[Function]}
options={

+ 0
- 0
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.tsx.snap View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save