@@ -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", |
@@ -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, |
@@ -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" |
@@ -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" |
@@ -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} |
@@ -30,7 +30,7 @@ exports[`Should render correctly 1`] = ` | |||
</Tooltip> | |||
</td> | |||
<td> | |||
<Select | |||
<SelectLegacy | |||
className="width100" | |||
clearable={false} | |||
disabled={false} |
@@ -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} |
@@ -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); |
@@ -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]} |
@@ -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} |
@@ -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} |
@@ -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} |
@@ -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')); |
@@ -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]} |
@@ -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} |
@@ -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} |
@@ -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" |
@@ -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} |
@@ -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 []} |
@@ -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" |
@@ -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} |
@@ -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]} |
@@ -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')} |
@@ -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) { |
@@ -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} |
@@ -43,7 +43,7 @@ exports[`render correctly 2`] = ` | |||
template | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<Select | |||
<SelectLegacy | |||
clearable={false} | |||
id="project-permissions-template" | |||
onChange={[Function]} |
@@ -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 |
@@ -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]} |
@@ -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} |
@@ -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} |
@@ -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} |
@@ -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'); | |||
}); | |||
@@ -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} |
@@ -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} |
@@ -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} |
@@ -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); | |||
} | |||
@@ -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(); |
@@ -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} |
@@ -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} |
@@ -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> | |||
); |
@@ -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> | |||
); | |||
} | |||
} |
@@ -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}> |
@@ -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> | |||
); | |||
} | |||
} |
@@ -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} /> | |||
); | |||
} |
@@ -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(); | |||
}); |
@@ -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); | |||
}); | |||
} |
@@ -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(); | |||
}); |
@@ -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> | |||
`; |
@@ -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> | |||
`; |
@@ -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", | |||
} | |||
} | |||
/> | |||
`; |
@@ -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> | |||
`; |
@@ -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} |
@@ -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' }); | |||
}); |
@@ -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} |
@@ -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} |
@@ -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'); | |||
}); | |||
@@ -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]} |
@@ -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} |
@@ -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} |
@@ -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} |
@@ -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} |
@@ -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" |
@@ -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'); |
@@ -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,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,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]} |
@@ -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} |
@@ -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} |
@@ -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'); | |||
@@ -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" |
@@ -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} |
@@ -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,7 +1,7 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders 1`] = ` | |||
<Select | |||
<SelectLegacy | |||
autoFocus={true} | |||
className="Select-big" | |||
clearable={false} |
@@ -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" |
@@ -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} |
@@ -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" |
@@ -10,7 +10,7 @@ exports[`should render correctly 1`] = ` | |||
quality_profiles.filter_by | |||
: | |||
</span> | |||
<Select | |||
<SelectLegacy | |||
className="input-medium" | |||
clearable={true} | |||
onChange={[Function]} |
@@ -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 }) => |
@@ -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(); | |||
@@ -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]} |
@@ -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} |
@@ -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' } })); |
@@ -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={ |
@@ -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} |
@@ -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(); | |||
@@ -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} |
@@ -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(); | |||
@@ -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} |
@@ -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} |
@@ -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]} |
@@ -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} |
@@ -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 }))} |
@@ -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} |
@@ -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' | |||
}) | |||
}; | |||
} |
@@ -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} />; | |||
} |
@@ -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} />); | |||
} | |||
}); |
@@ -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} /> | |||
); | |||
} | |||
}); |
@@ -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={ |