color: var(--darkBlue);
}
-/*
- * Radio
- */
-.icon-radio {
- position: relative;
- display: inline-block;
- vertical-align: top;
- width: 14px;
- height: 14px;
- margin: 1px;
- border: 1px solid var(--gray80);
- border-radius: 12px;
- box-sizing: border-box;
- transition: border-color 0.3s ease;
-}
-
-.icon-radio:after {
- position: absolute;
- top: 2px;
- left: 2px;
- display: block;
- width: 8px;
- height: 8px;
- border-radius: 8px;
- background-color: var(--darkBlue);
- content: '';
- opacity: 0;
- transition: opacity 0.3s ease;
-}
-
-a:not(.disabled):hover > .icon-radio {
- border-color: var(--blue);
-}
-
-.icon-radio.is-checked:after {
- opacity: 1;
-}
-
/*
* Common
*/
max-width: 700px;
}
-.manual-project-create .visibility-select-option {
- margin-left: 0 !important;
- margin-bottom: var(--gridSize);
- display: flex;
- align-items: center;
- font-size: var(--mediumFontSize);
-}
-
-.manual-project-create .visibility-details {
- display: block;
- margin: var(--gridSize) 0;
-}
-
-.manual-project-create .visibility-select-wrapper {
- padding: var(--gridSize) 0 calc(2 * var(--gridSize)) 0;
-}
-
.manual-project-create .button {
margin-top: var(--gridSize);
}
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { createProject, doesComponentExists } from '../../../api/components';
-import VisibilitySelector from '../../../components/common/VisibilitySelector';
import { isSonarCloud } from '../../../helpers/system';
import UpgradeOrganizationBox from '../components/UpgradeOrganizationBox';
import CreateProjectPageHeader from './CreateProjectPageHeader';
/>
</ValidationInput>
- {isSonarCloud() && selectedOrganization && (
- <div
- className={classNames('visibility-select-wrapper', {
- open: Boolean(this.state.selectedOrganization)
- })}>
- <VisibilitySelector
- canTurnToPrivate={canChoosePrivate}
- onChange={this.handleVisibilityChange}
- showDetails={true}
- visibility={canChoosePrivate ? this.state.selectedVisibility : 'public'}
- />
- </div>
- )}
-
<SubmitButton disabled={!this.canSubmit(this.state) || submitting}>
{translate('set_up')}
</SubmitButton>
import { subDays } from 'date-fns';
import { throttle } from 'lodash';
import * as React from 'react';
+import Radio from 'sonar-ui-common/components/controls/Radio';
import Select from 'sonar-ui-common/components/controls/Select';
import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
import DateFormatter from 'sonar-ui-common/components/intl/DateFormatter';
)}
<div className="analysis-selection-button">
- <i
- className={classNames('icon-radio', {
- 'is-checked': analysis.key === this.props.analysis
- })}
+ <Radio
+ checked={analysis.key === this.props.analysis}
+ onCheck={() => {}}
+ value=""
/>
</div>
</li>
<div
className="analysis-selection-button"
>
- <i
- className="icon-radio"
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value=""
/>
</div>
</li>
<div
className="analysis-selection-button"
>
- <i
- className="icon-radio"
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value=""
/>
</div>
</li>
<div
className="analysis-selection-button"
>
- <i
- className="icon-radio"
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value=""
/>
</div>
</li>
<div
className="analysis-selection-button"
>
- <i
- className="icon-radio"
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value=""
/>
</div>
</li>
* 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 classNames from 'classnames';
import * as React from 'react';
import { Button, ResetButtonLink } from 'sonar-ui-common/components/controls/buttons';
import Modal from 'sonar-ui-common/components/controls/Modal';
+import Radio from 'sonar-ui-common/components/controls/Radio';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
this.props.onClose();
};
- handleVisibilityClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
- const visibility = event.currentTarget.dataset.visibility as T.Visibility;
+ handleVisibilityChange = (visibility: T.Visibility) => {
this.setState({ visibility });
};
<div className="modal-body">
{['public', 'private'].map(visibility => (
<div className="big-spacer-bottom" key={visibility}>
- <p>
- {visibility === 'private' && !organization.canUpdateProjectsVisibilityToPrivate ? (
- <span className="text-muted cursor-not-allowed">
- <i
- className={classNames('icon-radio', 'spacer-right', {
- 'is-checked': this.state.visibility === visibility
- })}
- />
- {translate('visibility', visibility)}
- </span>
- ) : (
- <a
- className="link-base-color link-no-underline"
- data-visibility={visibility}
- href="#"
- onClick={this.handleVisibilityClick}>
- <i
- className={classNames('icon-radio', 'spacer-right', {
- 'is-checked': this.state.visibility === visibility
- })}
- />
- {translate('visibility', visibility)}
- </a>
- )}
- </p>
- <p className="text-muted spacer-top" style={{ paddingLeft: 22 }}>
- {translate('visibility', visibility, 'description.short')}
- </p>
+ <Radio
+ value={visibility}
+ checked={this.state.visibility === visibility}
+ onCheck={this.handleVisibilityChange}
+ disabled={
+ visibility === 'private' && !organization.canUpdateProjectsVisibilityToPrivate
+ }>
+ <div>
+ {translate('visibility', visibility)}
+ <p className="text-muted spacer-top">
+ {translate('visibility', visibility, 'description.short')}
+ </p>
+ </div>
+ </Radio>
</div>
))}
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import Radio from 'sonar-ui-common/components/controls/Radio';
import { click } from 'sonar-ui-common/helpers/testUtils';
import ChangeDefaultVisibilityForm from '../ChangeDefaultVisibilityForm';
const wrapper = shallowRender({ onConfirm });
expect(wrapper).toMatchSnapshot();
- click(wrapper.find('a[data-visibility="private"]'), {
- currentTarget: {
- blur() {},
- dataset: { visibility: 'private' }
- }
- });
+ wrapper
+ .find(Radio)
+ .first()
+ .props()
+ .onCheck('private');
expect(wrapper).toMatchSnapshot();
click(wrapper.find('.js-confirm'));
className="big-spacer-bottom"
key="public"
>
- <p>
- <a
- className="link-base-color link-no-underline"
- data-visibility="public"
- href="#"
- onClick={[Function]}
- >
- <i
- className="icon-radio spacer-right is-checked"
- />
- visibility.public
- </a>
- </p>
- <p
- className="text-muted spacer-top"
- style={
- Object {
- "paddingLeft": 22,
- }
- }
+ <Radio
+ checked={true}
+ disabled={false}
+ onCheck={[Function]}
+ value="public"
>
- visibility.public.description.short
- </p>
+ <div>
+ visibility.public
+ <p
+ className="text-muted spacer-top"
+ >
+ visibility.public.description.short
+ </p>
+ </div>
+ </Radio>
</div>
<div
className="big-spacer-bottom"
key="private"
>
- <p>
- <a
- className="link-base-color link-no-underline"
- data-visibility="private"
- href="#"
- onClick={[Function]}
- >
- <i
- className="icon-radio spacer-right"
- />
- visibility.private
- </a>
- </p>
- <p
- className="text-muted spacer-top"
- style={
- Object {
- "paddingLeft": 22,
- }
- }
+ <Radio
+ checked={false}
+ disabled={false}
+ onCheck={[Function]}
+ value="private"
>
- visibility.private.description.short
- </p>
+ <div>
+ visibility.private
+ <p
+ className="text-muted spacer-top"
+ >
+ visibility.private.description.short
+ </p>
+ </div>
+ </Radio>
</div>
<Alert
variant="warning"
className="big-spacer-bottom"
key="public"
>
- <p>
- <a
- className="link-base-color link-no-underline"
- data-visibility="public"
- href="#"
- onClick={[Function]}
- >
- <i
- className="icon-radio spacer-right"
- />
- visibility.public
- </a>
- </p>
- <p
- className="text-muted spacer-top"
- style={
- Object {
- "paddingLeft": 22,
- }
- }
+ <Radio
+ checked={false}
+ disabled={false}
+ onCheck={[Function]}
+ value="public"
>
- visibility.public.description.short
- </p>
+ <div>
+ visibility.public
+ <p
+ className="text-muted spacer-top"
+ >
+ visibility.public.description.short
+ </p>
+ </div>
+ </Radio>
</div>
<div
className="big-spacer-bottom"
key="private"
>
- <p>
- <a
- className="link-base-color link-no-underline"
- data-visibility="private"
- href="#"
- onClick={[Function]}
- >
- <i
- className="icon-radio spacer-right is-checked"
- />
- visibility.private
- </a>
- </p>
- <p
- className="text-muted spacer-top"
- style={
- Object {
- "paddingLeft": 22,
- }
- }
+ <Radio
+ checked={true}
+ disabled={false}
+ onCheck={[Function]}
+ value="private"
>
- visibility.private.description.short
- </p>
+ <div>
+ visibility.private
+ <p
+ className="text-muted spacer-top"
+ >
+ visibility.private.description.short
+ </p>
+ </div>
+ </Radio>
</div>
<Alert
variant="warning"
className="big-spacer-bottom"
key="public"
>
- <p>
- <a
- className="link-base-color link-no-underline"
- data-visibility="public"
- href="#"
- onClick={[Function]}
- >
- <i
- className="icon-radio spacer-right is-checked"
- />
- visibility.public
- </a>
- </p>
- <p
- className="text-muted spacer-top"
- style={
- Object {
- "paddingLeft": 22,
- }
- }
+ <Radio
+ checked={true}
+ disabled={false}
+ onCheck={[Function]}
+ value="public"
>
- visibility.public.description.short
- </p>
+ <div>
+ visibility.public
+ <p
+ className="text-muted spacer-top"
+ >
+ visibility.public.description.short
+ </p>
+ </div>
+ </Radio>
</div>
<div
className="big-spacer-bottom"
key="private"
>
- <p>
- <span
- className="text-muted cursor-not-allowed"
- >
- <i
- className="icon-radio spacer-right"
- />
- visibility.private
- </span>
- </p>
- <p
- className="text-muted spacer-top"
- style={
- Object {
- "paddingLeft": 22,
- }
- }
+ <Radio
+ checked={false}
+ disabled={true}
+ onCheck={[Function]}
+ value="private"
>
- visibility.private.description.short
- </p>
+ <div>
+ visibility.private
+ <p
+ className="text-muted spacer-top"
+ >
+ visibility.private.description.short
+ </p>
+ </div>
+ </Radio>
</div>
</div>
<footer
* 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 classNames from 'classnames';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import { Button, DeleteButton, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
+import Radio from 'sonar-ui-common/components/controls/Radio';
import AlertErrorIcon from 'sonar-ui-common/components/icons/AlertErrorIcon';
import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
this.setState({ selection: 'use-existing' });
};
+ handleModeChange = (mode: string) => {
+ this.setState({ selection: mode });
+ };
+
handleExisingTokenChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ existingToken: event.currentTarget.value });
};
renderGenerateOption = () => (
<div>
{this.state.tokens !== undefined && this.state.tokens.length > 0 ? (
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={this.handleGenerateClick}>
- <i
- className={classNames('icon-radio', 'spacer-right', {
- 'is-checked': this.state.selection === 'generate'
- })}
- />
+ <Radio
+ checked={this.state.selection === 'generate'}
+ onCheck={this.handleModeChange}
+ value="generate">
{translate('onboarding.token.generate_token')}
- </a>
+ </Radio>
) : (
translate('onboarding.token.generate_token')
)}
return (
<div className="big-spacer-top">
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={this.handleUseExistingClick}>
- <i
- className={classNames('icon-radio', 'spacer-right', {
- 'is-checked': this.state.selection === 'use-existing'
- })}
- />
+ <Radio
+ checked={this.state.selection === 'use-existing'}
+ onCheck={this.handleModeChange}
+ value="use-existing">
{translate('onboarding.token.use_existing_token')}
- </a>
+ </Radio>
{this.state.selection === 'use-existing' && (
<div className="big-spacer-top">
<input
>
<div>
<div>
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={[Function]}
+ <Radio
+ checked={true}
+ onCheck={[Function]}
+ value="generate"
>
- <i
- className="icon-radio spacer-right is-checked"
- />
onboarding.token.generate_token
- </a>
+ </Radio>
<div
className="big-spacer-top"
>
<div
className="big-spacer-top"
>
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={[Function]}
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value="use-existing"
>
- <i
- className="icon-radio spacer-right"
- />
onboarding.token.use_existing_token
- </a>
+ </Radio>
</div>
</div>
<div
>
<div>
<div>
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={[Function]}
+ <Radio
+ checked={true}
+ onCheck={[Function]}
+ value="generate"
>
- <i
- className="icon-radio spacer-right is-checked"
- />
onboarding.token.generate_token
- </a>
+ </Radio>
<div
className="big-spacer-top"
>
<div
className="big-spacer-top"
>
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={[Function]}
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value="use-existing"
>
- <i
- className="icon-radio spacer-right"
- />
onboarding.token.use_existing_token
- </a>
+ </Radio>
</div>
</div>
<div
>
<div>
<div>
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={[Function]}
+ <Radio
+ checked={true}
+ onCheck={[Function]}
+ value="generate"
>
- <i
- className="icon-radio spacer-right is-checked"
- />
onboarding.token.generate_token
- </a>
+ </Radio>
<div
className="big-spacer-top"
>
<div
className="big-spacer-top"
>
- <a
- className="js-new link-base-color link-no-underline"
- href="#"
- onClick={[Function]}
+ <Radio
+ checked={false}
+ onCheck={[Function]}
+ value="use-existing"
>
- <i
- className="icon-radio spacer-right"
- />
onboarding.token.use_existing_token
- </a>
+ </Radio>
</div>
</div>
<div
*/
import * as classNames from 'classnames';
import * as React from 'react';
+import Radio from 'sonar-ui-common/components/controls/Radio';
import { translate } from 'sonar-ui-common/helpers/l10n';
interface Props {
}
export default class VisibilitySelector extends React.PureComponent<Props> {
- handlePublicClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
- this.props.onChange('public');
- };
-
- handlePrivateClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
- this.props.onChange('private');
- };
-
render() {
return (
- <div className={classNames('visibility-select', this.props.className)}>
- <a
- className="link-base-color link-no-underline visibility-select-option"
- href="#"
- id="visibility-public"
- onClick={this.handlePublicClick}>
- <i
- className={classNames('icon-radio', {
- 'is-checked': this.props.visibility === 'public'
- })}
- />
- <span className="spacer-left">{translate('visibility.public')}</span>
- </a>
- {this.props.showDetails && (
- <span className="visibility-details note">
- {translate('visibility.public.description.long')}
- </span>
- )}
-
- {this.props.canTurnToPrivate ? (
- <>
- <a
- className="link-base-color link-no-underline huge-spacer-left visibility-select-option"
- href="#"
- id="visibility-private"
- onClick={this.handlePrivateClick}>
- <i
- className={classNames('icon-radio', {
- 'is-checked': this.props.visibility === 'private'
- })}
- />
- <span className="spacer-left">{translate('visibility.private')}</span>
- </a>
- {this.props.showDetails && (
- <span className="visibility-details note">
- {translate('visibility.private.description.long')}
- </span>
- )}
- </>
- ) : (
- <>
- <span
- className="huge-spacer-left text-muted cursor-not-allowed visibility-select-option"
- id="visibility-private">
- <i
- className={classNames('icon-radio', {
- 'is-checked': this.props.visibility === 'private'
- })}
- />
- <span className="spacer-left">{translate('visibility.private')}</span>
- </span>
- {this.props.showDetails && (
- <span className="visibility-details note">
- {translate('visibility.private.description.long')}
- </span>
- )}
- </>
- )}
+ <div className={classNames(this.props.className)}>
+ {['public', 'private'].map(visibility => (
+ <Radio
+ className={`huge-spacer-right visibility-${visibility}`}
+ key={visibility}
+ value={visibility}
+ checked={this.props.visibility === visibility}
+ onCheck={this.props.onChange}
+ disabled={visibility === 'private' && !this.props.canTurnToPrivate}>
+ <div>
+ {translate('visibility', visibility)}
+ {this.props.showDetails && (
+ <p className="note">{translate('visibility', visibility, 'description.long')}</p>
+ )}
+ </div>
+ </Radio>
+ ))}
</div>
);
}
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { click } from 'sonar-ui-common/helpers/testUtils';
+import Radio from 'sonar-ui-common/components/controls/Radio';
import VisibilitySelector from '../VisibilitySelector';
it('changes visibility', () => {
const onChange = jest.fn();
- const wrapper = shallow(
- <VisibilitySelector canTurnToPrivate={true} onChange={onChange} visibility="public" />
- );
+ const wrapper = shallowRender({ onChange });
expect(wrapper).toMatchSnapshot();
- click(wrapper.find('#visibility-private'));
+ wrapper
+ .find(Radio)
+ .first()
+ .props()
+ .onCheck('private');
expect(onChange).toBeCalledWith('private');
wrapper.setProps({ visibility: 'private' });
expect(wrapper).toMatchSnapshot();
- click(wrapper.find('#visibility-public'));
+ wrapper
+ .find(Radio)
+ .first()
+ .props()
+ .onCheck('public');
expect(onChange).toBeCalledWith('public');
});
it('renders disabled', () => {
- expect(
- shallow(
- <VisibilitySelector canTurnToPrivate={false} onChange={jest.fn()} visibility="public" />
- )
- ).toMatchSnapshot();
+ expect(shallowRender({ canTurnToPrivate: false })).toMatchSnapshot();
});
+
+function shallowRender(props?: Partial<VisibilitySelector['props']>) {
+ return shallow<VisibilitySelector>(
+ <VisibilitySelector
+ className="test-classname"
+ canTurnToPrivate={true}
+ onChange={jest.fn()}
+ visibility="public"
+ {...props}
+ />
+ );
+}
exports[`changes visibility 1`] = `
<div
- className="visibility-select"
+ className="test-classname"
>
- <a
- className="link-base-color link-no-underline visibility-select-option"
- href="#"
- id="visibility-public"
- onClick={[Function]}
+ <Radio
+ checked={true}
+ className="huge-spacer-right visibility-public"
+ disabled={false}
+ key="public"
+ onCheck={[MockFunction]}
+ value="public"
>
- <i
- className="icon-radio is-checked"
- />
- <span
- className="spacer-left"
- >
+ <div>
visibility.public
- </span>
- </a>
- <a
- className="link-base-color link-no-underline huge-spacer-left visibility-select-option"
- href="#"
- id="visibility-private"
- onClick={[Function]}
+ </div>
+ </Radio>
+ <Radio
+ checked={false}
+ className="huge-spacer-right visibility-private"
+ disabled={false}
+ key="private"
+ onCheck={[MockFunction]}
+ value="private"
>
- <i
- className="icon-radio"
- />
- <span
- className="spacer-left"
- >
+ <div>
visibility.private
- </span>
- </a>
+ </div>
+ </Radio>
</div>
`;
exports[`changes visibility 2`] = `
<div
- className="visibility-select"
+ className="test-classname"
>
- <a
- className="link-base-color link-no-underline visibility-select-option"
- href="#"
- id="visibility-public"
- onClick={[Function]}
+ <Radio
+ checked={false}
+ className="huge-spacer-right visibility-public"
+ disabled={false}
+ key="public"
+ onCheck={
+ [MockFunction] {
+ "calls": Array [
+ Array [
+ "private",
+ ],
+ ],
+ "results": Array [
+ Object {
+ "type": "return",
+ "value": undefined,
+ },
+ ],
+ }
+ }
+ value="public"
>
- <i
- className="icon-radio"
- />
- <span
- className="spacer-left"
- >
+ <div>
visibility.public
- </span>
- </a>
- <a
- className="link-base-color link-no-underline huge-spacer-left visibility-select-option"
- href="#"
- id="visibility-private"
- onClick={[Function]}
+ </div>
+ </Radio>
+ <Radio
+ checked={true}
+ className="huge-spacer-right visibility-private"
+ disabled={false}
+ key="private"
+ onCheck={
+ [MockFunction] {
+ "calls": Array [
+ Array [
+ "private",
+ ],
+ ],
+ "results": Array [
+ Object {
+ "type": "return",
+ "value": undefined,
+ },
+ ],
+ }
+ }
+ value="private"
>
- <i
- className="icon-radio is-checked"
- />
- <span
- className="spacer-left"
- >
+ <div>
visibility.private
- </span>
- </a>
+ </div>
+ </Radio>
</div>
`;
exports[`renders disabled 1`] = `
<div
- className="visibility-select"
+ className="test-classname"
>
- <a
- className="link-base-color link-no-underline visibility-select-option"
- href="#"
- id="visibility-public"
- onClick={[Function]}
+ <Radio
+ checked={true}
+ className="huge-spacer-right visibility-public"
+ disabled={false}
+ key="public"
+ onCheck={[MockFunction]}
+ value="public"
>
- <i
- className="icon-radio is-checked"
- />
- <span
- className="spacer-left"
- >
+ <div>
visibility.public
- </span>
- </a>
- <span
- className="huge-spacer-left text-muted cursor-not-allowed visibility-select-option"
- id="visibility-private"
+ </div>
+ </Radio>
+ <Radio
+ checked={false}
+ className="huge-spacer-right visibility-private"
+ disabled={true}
+ key="private"
+ onCheck={[MockFunction]}
+ value="private"
>
- <i
- className="icon-radio"
- />
- <span
- className="spacer-left"
- >
+ <div>
visibility.private
- </span>
- </span>
+ </div>
+ </Radio>
</div>
`;