import { Helmet } from 'react-helmet-async';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
+import { components, OptionProps } from 'react-select';
import A11ySkipTarget from '../../app/components/a11y/A11ySkipTarget';
import Suggestions from '../../app/components/embed-docs-modal/Suggestions';
import DisableableSelectOption from '../../components/common/DisableableSelectOption';
import { SubmitButton } from '../../components/controls/buttons';
import HelpTooltip from '../../components/controls/HelpTooltip';
import Radio from '../../components/controls/Radio';
-import SelectLegacy from '../../components/controls/SelectLegacy';
+import Select, { BasicSelectOption } from '../../components/controls/Select';
import { Alert } from '../../components/ui/Alert';
import { translate } from '../../helpers/l10n';
import { isDiffMetric } from '../../helpers/measures';
return !!qualityGate.conditions?.some(condition => isDiffMetric(condition.metric));
}
+interface QualityGateOption extends BasicSelectOption {
+ isDisabled: boolean;
+}
+
+function renderQualitygateOption(props: OptionProps<QualityGateOption, false>) {
+ return (
+ <components.Option {...props}>
+ <div>
+ <DisableableSelectOption
+ className="abs-width-100"
+ option={props.data}
+ disabledReason={translate('project_quality_gate.no_condition.reason')}
+ disableTooltipOverlay={() => (
+ <FormattedMessage
+ id="project_quality_gate.no_condition"
+ defaultMessage={translate('project_quality_gate.no_condition')}
+ values={{
+ link: (
+ <Link to={{ pathname: `/quality_gates/show/${props.data.value}` }}>
+ {translate('project_quality_gate.no_condition.link')}
+ </Link>
+ )
+ }}
+ />
+ )}
+ />
+ </div>
+ </components.Option>
+ );
+}
+
export default function ProjectQualityGateAppRenderer(props: ProjectQualityGateAppRendererProps) {
const { allQualityGates, currentQualityGate, loading, selectedQualityGateId, submitting } = props;
const defaultQualityGate = allQualityGates?.find(g => g.isDefault);
const selectedQualityGate = allQualityGates.find(qg => qg.id === selectedQualityGateId);
- const options = allQualityGates.map(g => ({
- disabled: g.conditions === undefined || g.conditions.length === 0,
+ const options: QualityGateOption[] = allQualityGates.map(g => ({
+ isDisabled: g.conditions === undefined || g.conditions.length === 0,
label: g.name,
value: g.id
}));
className="display-flex-start"
checked={!usesDefault}
disabled={submitting}
- onCheck={value => props.onSelect(value)}
+ onCheck={value => {
+ if (usesDefault) {
+ props.onSelect(value);
+ }
+ }}
value={!usesDefault ? selectedQualityGateId : currentQualityGate.id}>
<div className="spacer-left">
<div className="little-spacer-bottom">
{translate('project_quality_gate.always_use_specific')}
</div>
<div className="display-flex-center">
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={submitting || usesDefault}
- onChange={({ value }: { value: string }) => props.onSelect(value)}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={{
+ Option: renderQualitygateOption
+ }}
+ isClearable={usesDefault}
+ isDisabled={submitting || usesDefault}
+ onChange={({ value }: QualityGateOption) => {
+ props.onSelect(value);
+ }}
options={options}
- optionRenderer={option => (
- <DisableableSelectOption
- className="abs-width-100"
- option={option}
- disabledReason={translate('project_quality_gate.no_condition.reason')}
- disableTooltipOverlay={() => (
- <FormattedMessage
- id="project_quality_gate.no_condition"
- defaultMessage={translate('project_quality_gate.no_condition')}
- values={{
- link: (
- <Link to={{ pathname: `/quality_gates/show/${option.value}` }}>
- {translate('project_quality_gate.no_condition.link')}
- </Link>
- )
- }}
- />
- )}
- />
- )}
- value={selectedQualityGateId}
+ value={options.find(o => o.value === selectedQualityGateId)}
/>
</div>
</div>
import { shallow } from 'enzyme';
import * as React from 'react';
import Radio from '../../../components/controls/Radio';
-import SelectLegacy from '../../../components/controls/SelectLegacy';
+import Select from '../../../components/controls/Select';
import { mockQualityGate } from '../../../helpers/mocks/quality-gates';
import { mockCondition } from '../../../helpers/testMocks';
import { submit } from '../../../helpers/testUtils';
it('should render select options correctly', () => {
return new Promise<void>(resolve => {
const wrapper = shallowRender();
- const render = wrapper.find(SelectLegacy).props().optionRenderer;
+ const render = wrapper.find(Select).props().components.Option;
expect(render).toBeDefined();
- expect(render!({ value: '1', label: 'Gate 1' })).toMatchSnapshot('default');
+ expect(render({ data: { value: '1', label: 'Gate 1' } })).toMatchSnapshot('default');
resolve();
});
});
.onCheck('1');
expect(onSelect).toHaveBeenLastCalledWith('1');
- wrapper.find(SelectLegacy).props().onChange!({ value: '2' });
+ wrapper.find(Select).props().onChange!({ value: '2' });
expect(onSelect).toHaveBeenLastCalledWith('2');
});
<div
className="display-flex-center"
>
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={true}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isClearable={true}
+ isDisabled={true}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "1",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "2",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "3",
},
]
}
- value="-1"
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={false}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isClearable={false}
+ isDisabled={false}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "1",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "2",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "3",
},
]
}
- value="1"
+ value={
+ Object {
+ "isDisabled": false,
+ "label": "qualitygate",
+ "value": "1",
+ }
+ }
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={false}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isClearable={false}
+ isDisabled={false}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "1",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "2",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "3",
},
]
}
- value="3"
+ value={
+ Object {
+ "isDisabled": false,
+ "label": "qualitygate",
+ "value": "3",
+ }
+ }
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={false}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isClearable={false}
+ isDisabled={false}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "1",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "2",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "3",
},
]
}
- value="5"
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={true}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isClearable={true}
+ isDisabled={true}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "1",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "2",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "3",
},
]
}
- value="-1"
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
- className="abs-width-300"
- clearable={false}
- disabled={true}
+ <Select
+ className="abs-width-300 it__project-quality-gate-select"
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isClearable={false}
+ isDisabled={true}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "1",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "2",
},
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "qualitygate",
"value": "3",
},
]
}
- value="1"
+ value={
+ Object {
+ "isDisabled": false,
+ "label": "qualitygate",
+ "value": "1",
+ }
+ }
/>
</div>
</div>
`;
exports[`should render select options correctly: default 1`] = `
-<DisableableSelectOption
- className="abs-width-100"
- disableTooltipOverlay={[Function]}
- disabledReason="project_quality_gate.no_condition.reason"
- option={
+<Option
+ data={
Object {
"label": "Gate 1",
"value": "1",
}
}
-/>
+>
+ <div>
+ <DisableableSelectOption
+ className="abs-width-100"
+ disableTooltipOverlay={[Function]}
+ disabledReason="project_quality_gate.no_condition.reason"
+ option={
+ Object {
+ "label": "Gate 1",
+ "value": "1",
+ }
+ }
+ />
+ </div>
+</Option>
`;
*/
import { difference } from 'lodash';
import * as React from 'react';
-import { Link } from 'react-router';
import { Profile } from '../../../api/quality-profiles';
import withLanguagesContext from '../../../app/components/languages/withLanguagesContext';
-import DisableableSelectOption from '../../../components/common/DisableableSelectOption';
import { ButtonLink, SubmitButton } from '../../../components/controls/buttons';
-import SelectLegacy from '../../../components/controls/SelectLegacy';
+import Select, { BasicSelectOption } from '../../../components/controls/Select';
import SimpleModal from '../../../components/controls/SimpleModal';
import { translate } from '../../../helpers/l10n';
-import { getQualityProfileUrl } from '../../../helpers/urls';
import { Languages } from '../../../types/languages';
import { Dict } from '../../../types/types';
+import LanguageProfileSelectOption, { ProfileOption } from './LanguageProfileSelectOption';
export interface AddLanguageModalProps {
languages: Languages;
const header = translate('project_quality_profile.add_language_modal.title');
- const languageOptions = difference(
+ const languageOptions: BasicSelectOption[] = difference(
Object.keys(profilesByLanguage),
unavailableLanguages
).map(l => ({ value: l, label: languages[l].name }));
- const profileOptions =
+ const profileOptions: ProfileOption[] =
language !== undefined
? profilesByLanguage[language].map(p => ({
value: p.key,
label: p.name,
- disabled: p.activeRuleCount === 0
+ language,
+ isDisabled: p.activeRuleCount === 0
}))
: [];
{translate('project_quality_profile.add_language_modal.choose_language')}
</label>
</div>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={submitting}
+ isDisabled={submitting}
id="language"
- onChange={({ value }: { value: string }) => setSelected({ language: value })}
+ onChange={({ value }: BasicSelectOption) => {
+ setSelected({ language: value, key: undefined });
+ }}
options={languageOptions}
- value={language}
/>
</div>
{translate('project_quality_profile.add_language_modal.choose_profile')}
</label>
</div>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={submitting || !language}
+ isDisabled={submitting || !language}
id="profiles"
- onChange={({ value }: { value: string }) => setSelected({ language, key: value })}
+ onChange={({ value }: ProfileOption) => setSelected({ language, key: value })}
options={profileOptions}
- optionRenderer={option => (
- <DisableableSelectOption
- option={option}
- disabledReason={translate(
- 'project_quality_profile.add_language_modal.no_active_rules'
- )}
- disableTooltipOverlay={() => (
- <>
- <p>
- {translate(
- 'project_quality_profile.add_language_modal.profile_unavailable_no_active_rules'
- )}
- </p>
- {option.label && language && (
- <Link to={getQualityProfileUrl(option.label, language)}>
- {translate(
- 'project_quality_profile.add_language_modal.go_to_profile'
- )}
- </Link>
- )}
- </>
- )}
- />
- )}
- value={key}
+ components={{
+ Option: LanguageProfileSelectOption
+ }}
+ value={profileOptions.find(o => o.value === key) ?? null}
/>
</div>
</div>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { Link } from 'react-router';
+import { components, OptionProps } from 'react-select';
+import DisableableSelectOption from '../../../components/common/DisableableSelectOption';
+import { BasicSelectOption } from '../../../components/controls/Select';
+import { translate } from '../../../helpers/l10n';
+import { getQualityProfileUrl } from '../../../helpers/urls';
+
+export interface ProfileOption extends BasicSelectOption {
+ language: string;
+ isDisabled: boolean;
+}
+
+export type LanguageProfileSelectOptionProps = OptionProps<ProfileOption, false>;
+
+export default function LanguageProfileSelectOption(props: LanguageProfileSelectOptionProps) {
+ const option = props.data;
+
+ return (
+ <components.Option {...props}>
+ <div>
+ <DisableableSelectOption
+ option={option}
+ disabledReason={translate('project_quality_profile.add_language_modal.no_active_rules')}
+ disableTooltipOverlay={() => (
+ <>
+ <p>
+ {translate(
+ 'project_quality_profile.add_language_modal.profile_unavailable_no_active_rules'
+ )}
+ </p>
+ {option.label && option.language && (
+ <Link to={getQualityProfileUrl(option.label, option.language)}>
+ {translate('project_quality_profile.add_language_modal.go_to_profile')}
+ </Link>
+ )}
+ </>
+ )}
+ />
+ </div>
+ </components.Option>
+ );
+}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-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 Radio from '../../../components/controls/Radio';
-import SelectLegacy from '../../../components/controls/SelectLegacy';
+import Select from '../../../components/controls/Select';
import SimpleModal from '../../../components/controls/SimpleModal';
import { Alert } from '../../../components/ui/Alert';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { getQualityProfileUrl } from '../../../helpers/urls';
import { Component } from '../../../types/types';
import BuiltInQualityProfileBadge from '../../quality-profiles/components/BuiltInQualityProfileBadge';
import { USE_SYSTEM_DEFAULT } from '../constants';
+import LanguageProfileSelectOption, { ProfileOption } from './LanguageProfileSelectOption';
export interface SetQualityProfileModalProps {
availableProfiles: Profile[];
'project_quality_profile.change_lang_X_profile',
currentProfile.languageName
);
- const profileOptions = availableProfiles.map(p => ({
+ const profileOptions: ProfileOption[] = availableProfiles.map(p => ({
value: p.key,
label: p.name,
- disabled: p.activeRuleCount === 0
+ language: currentProfile.language,
+ isDisabled: p.activeRuleCount === 0
}));
const hasSelectedSysDefault = selected === USE_SYSTEM_DEFAULT;
const hasChanged = usesDefault ? !hasSelectedSysDefault : selected !== currentProfile.key;
{translate('project_quality_profile.always_use_specific')}
</div>
<div className="display-flex-center">
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={submitting || hasSelectedSysDefault}
- onChange={({ value }: { value: string }) => setSelected(value)}
+ isDisabled={submitting || hasSelectedSysDefault}
+ onChange={({ value }: ProfileOption) => setSelected(value)}
options={profileOptions}
- optionRenderer={option => (
- <DisableableSelectOption
- option={option}
- disabledReason={translate(
- 'project_quality_profile.add_language_modal.no_active_rules'
- )}
- disableTooltipOverlay={() => (
- <>
- <p>
- {translate(
- 'project_quality_profile.add_language_modal.profile_unavailable_no_active_rules'
- )}
- </p>
- {option.label && (
- <Link
- to={getQualityProfileUrl(
- option.label,
- currentProfile.language
- )}>
- {translate(
- 'project_quality_profile.add_language_modal.go_to_profile'
- )}
- </Link>
- )}
- </>
- )}
- />
+ components={{
+ Option: LanguageProfileSelectOption
+ }}
+ value={profileOptions.find(
+ option =>
+ option.value ===
+ (!hasSelectedSysDefault ? selected : currentProfile.key)
)}
- value={!hasSelectedSysDefault ? selected : currentProfile.key}
/>
</div>
</div>
*/
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
-import SelectLegacy from '../../../../components/controls/SelectLegacy';
+import Select from '../../../../components/controls/Select';
import SimpleModal from '../../../../components/controls/SimpleModal';
import { mockQualityProfile } from '../../../../helpers/testMocks';
import { AddLanguageModal, AddLanguageModalProps } from '../AddLanguageModal';
expect(diveIntoSimpleModal(shallowRender())).toMatchSnapshot('default');
});
-it('should render select options correctly', () => {
- return new Promise<void>((resolve, reject) => {
- const wrapper = shallowRender();
-
- const langOnChange = getLanguageSelect(wrapper).props().onChange;
- if (!langOnChange) {
- reject();
- return;
- }
- langOnChange({ value: 'js' });
-
- const render = getProfileSelect(wrapper).props().optionRenderer;
- if (!render) {
- reject();
- return;
- }
- expect(render({ value: 'bar', label: 'Profile 1' })).toMatchSnapshot('default');
- resolve();
- });
-});
-
it('should correctly handle changes', () => {
const onSubmit = jest.fn();
const wrapper = shallowRender({ onSubmit });
profileSelect = getProfileSelect(wrapper);
expect(profileSelect.props().options).toHaveLength(2);
expect(profileSelect.props().options).toEqual(
- expect.arrayContaining([expect.objectContaining({ disabled: true })])
+ expect.arrayContaining([expect.objectContaining({ isDisabled: true })])
);
// Choose 1 profile.
function getLanguageSelect(wrapper: ShallowWrapper) {
return diveIntoSimpleModal(wrapper)
- .find(SelectLegacy)
+ .find(Select)
.at(0);
}
function getProfileSelect(wrapper: ShallowWrapper) {
return diveIntoSimpleModal(wrapper)
- .find(SelectLegacy)
+ .find(Select)
.at(1);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 DisableableSelectOption from '../../../../components/common/DisableableSelectOption';
+import { mockProfileOption } from '../../../../helpers/mocks/quality-profiles';
+import LanguageProfileSelectOption, {
+ LanguageProfileSelectOptionProps,
+ ProfileOption
+} from '../LanguageProfileSelectOption';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot('default');
+});
+
+describe('tooltip', () => {
+ it('should render correctly', () => {
+ expect(renderTooltipOverly()).toMatchSnapshot('default');
+ expect(renderTooltipOverly({ label: undefined })).toMatchSnapshot('no link');
+ });
+});
+
+function renderTooltipOverly(overrides: Partial<ProfileOption> = {}) {
+ const wrapper = shallowRender(overrides);
+ const { disableTooltipOverlay } = wrapper.find(DisableableSelectOption).props();
+ return disableTooltipOverlay();
+}
+
+function shallowRender(overrides: Partial<ProfileOption> = {}) {
+ // satisfy the required props that the option actually gets from the select
+ const optionProps = {} as LanguageProfileSelectOptionProps;
+ return shallow(
+ <LanguageProfileSelectOption {...optionProps} data={{ ...mockProfileOption(), ...overrides }} />
+ );
+}
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
import Radio from '../../../../components/controls/Radio';
-import SelectLegacy from '../../../../components/controls/SelectLegacy';
+import Select from '../../../../components/controls/Select';
import SimpleModal from '../../../../components/controls/SimpleModal';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockQualityProfile } from '../../../../helpers/testMocks';
expect(shallowRender({ component: mockComponent() })).toMatchSnapshot('needs reanalysis');
});
-it('should render select options correctly', () => {
- return new Promise<void>((resolve, reject) => {
- const wrapper = shallowRender();
- const render = wrapper.find(SelectLegacy).props().optionRenderer;
- if (!render) {
- reject();
- return;
- }
- expect(render({ value: 'bar', label: 'Profile 1' })).toMatchSnapshot('default');
- resolve();
- });
-});
-
it('should correctly handle changes', () => {
const onSubmit = jest.fn();
const wrapper = shallowRender({ onSubmit }, false);
expect(onSubmit).toHaveBeenLastCalledWith('foo', 'foo');
const change = diveIntoSimpleModal(wrapper)
- .find(SelectLegacy)
+ .find(Select)
.props().onChange;
expect(change).toBeDefined();
project_quality_profile.add_language_modal.choose_language
</label>
</div>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={false}
id="language"
+ isDisabled={false}
onChange={[Function]}
options={
Array [
project_quality_profile.add_language_modal.choose_profile
</label>
</div>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={true}
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
id="profiles"
+ isDisabled={true}
onChange={[Function]}
- optionRenderer={[Function]}
options={Array []}
+ value={null}
/>
</div>
</div>
</form>,
]
`;
-
-exports[`should render select options correctly: default 1`] = `
-<DisableableSelectOption
- disableTooltipOverlay={[Function]}
- disabledReason="project_quality_profile.add_language_modal.no_active_rules"
- option={
- Object {
- "label": "Profile 1",
- "value": "bar",
- }
- }
-/>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: default 1`] = `
+<Option
+ data={
+ Object {
+ "isDisabled": false,
+ "label": "Profile 1",
+ "language": "Java",
+ "value": "profile-1",
+ }
+ }
+>
+ <div>
+ <DisableableSelectOption
+ disableTooltipOverlay={[Function]}
+ disabledReason="project_quality_profile.add_language_modal.no_active_rules"
+ option={
+ Object {
+ "isDisabled": false,
+ "label": "Profile 1",
+ "language": "Java",
+ "value": "profile-1",
+ }
+ }
+ />
+ </div>
+</Option>
+`;
+
+exports[`tooltip should render correctly: default 1`] = `
+<React.Fragment>
+ <p>
+ project_quality_profile.add_language_modal.profile_unavailable_no_active_rules
+ </p>
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/profiles/show",
+ "query": Object {
+ "language": "Java",
+ "name": "Profile 1",
+ },
+ }
+ }
+ >
+ project_quality_profile.add_language_modal.go_to_profile
+ </Link>
+</React.Fragment>
+`;
+
+exports[`tooltip should render correctly: no link 1`] = `
+<React.Fragment>
+ <p>
+ project_quality_profile.add_language_modal.profile_unavailable_no_active_rules
+ </p>
+</React.Fragment>
+`;
<div
className="display-flex-center"
>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={false}
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isDisabled={false}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "name",
+ "language": "js",
"value": "foo",
},
Object {
- "disabled": true,
+ "isDisabled": true,
"label": "name",
+ "language": "js",
"value": "bar",
},
]
}
- value="foo"
+ value={
+ Object {
+ "isDisabled": false,
+ "label": "name",
+ "language": "js",
+ "value": "foo",
+ }
+ }
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={true}
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isDisabled={true}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "name",
+ "language": "js",
"value": "foo",
},
Object {
- "disabled": true,
+ "isDisabled": true,
"label": "name",
+ "language": "js",
"value": "bar",
},
]
}
- value="foo"
+ value={
+ Object {
+ "isDisabled": false,
+ "label": "name",
+ "language": "js",
+ "value": "foo",
+ }
+ }
/>
</div>
</div>
<div
className="display-flex-center"
>
- <SelectLegacy
+ <Select
className="abs-width-300"
- clearable={false}
- disabled={false}
+ components={
+ Object {
+ "Option": [Function],
+ }
+ }
+ isDisabled={false}
onChange={[Function]}
- optionRenderer={[Function]}
options={
Array [
Object {
- "disabled": false,
+ "isDisabled": false,
"label": "name",
+ "language": "js",
"value": "foo",
},
Object {
- "disabled": true,
+ "isDisabled": true,
"label": "name",
+ "language": "js",
"value": "bar",
},
]
}
- value="foo"
+ value={
+ Object {
+ "isDisabled": false,
+ "label": "name",
+ "language": "js",
+ "value": "foo",
+ }
+ }
/>
</div>
</div>
</form>,
]
`;
-
-exports[`should render select options correctly: default 1`] = `
-<DisableableSelectOption
- disableTooltipOverlay={[Function]}
- disabledReason="project_quality_profile.add_language_modal.no_active_rules"
- option={
- Object {
- "label": "Profile 1",
- "value": "bar",
- }
- }
-/>
-`;
export interface DisableableSelectOptionProps {
className?: string;
disabledReason?: string;
- option: { label?: string; value?: string | number | boolean; disabled?: boolean };
+ option: { label?: string; value?: string | number | boolean; isDisabled?: boolean };
disableTooltipOverlay: () => React.ReactNode;
}
export default function DisableableSelectOption(props: DisableableSelectOptionProps) {
const { option, disableTooltipOverlay, disabledReason, className = '' } = props;
const label = option.label || option.value;
- return option.disabled ? (
+ return option.isDisabled ? (
<Tooltip overlay={disableTooltipOverlay()} placement="left">
<span className={className}>
{label}
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ option: { value: 'baz' } })).toMatchSnapshot('no label');
- expect(shallowRender({ option: { label: 'Bar', value: 'bar', disabled: true } })).toMatchSnapshot(
- 'disabled'
- );
+ expect(
+ shallowRender({ option: { label: 'Bar', value: 'bar', isDisabled: true } })
+ ).toMatchSnapshot('disabled');
expect(
shallowRender({
- option: { label: 'Bar', value: 'bar', disabled: true },
+ option: { label: 'Bar', value: 'bar', isDisabled: true },
disabledReason: 'bar baz'
})
).toMatchSnapshot('disabled, with explanation');
border: `1px solid ${state.isFocused ? colors.blue : colors.gray80}`,
borderCollapse: 'separate',
borderRadius: '2px',
- backgroundColor: '#fff',
+ backgroundColor: state.isDisabled ? colors.disableGrayBg : '#fff',
boxSizing: 'border-box',
color: `${colors.baseFontColor}`,
cursor: 'default',
display: 'flex'
};
},
- indicatorsContainer: () => ({
+ indicatorsContainer: (_provided, state) => ({
position: 'relative',
- cursor: 'pointer',
+ cursor: state.isDisabled ? 'default' : 'pointer',
textAlign: 'end',
verticalAlign: 'middle',
width: '20px',
lineHeight: '20px',
padding: '0 8px',
boxSizing: 'border-box',
- color: `${colors.baseFontColor}`,
- backgroundColor: state.isFocused ? `${colors.barBackgroundColor}` : 'white',
+ color: state.isDisabled ? colors.disableGrayText : colors.baseFontColor,
+ backgroundColor: state.isFocused ? colors.barBackgroundColor : colors.white,
fontSize: `${sizes.smallFontSize}`,
- cursor: 'pointer',
+ cursor: state.isDisabled ? 'default' : 'pointer',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { ProfileOption } from '../../apps/projectQualityProfiles/components/LanguageProfileSelectOption';
+
+export function mockProfileOption(overrides: Partial<ProfileOption> = {}): ProfileOption {
+ return {
+ value: 'profile-1',
+ label: 'Profile 1',
+ language: 'Java',
+ isDisabled: false,
+ ...overrides
+ };
+}