</div>
<div className="page-description">
{translateWithParameters(
- 'onboarding.header.description_x',
+ 'onboarding.header.description',
organizationsEnabled ? 3 : 2
)}
</div>
*/
// @flow
import React from 'react';
+import classNames from 'classnames';
import Step from './Step';
import CloseIcon from '../../../components/icons-components/CloseIcon';
import { generateToken, revokeToken } from '../../../api/user-tokens';
/*::
type State = {
+ existingToken:string,
loading: boolean,
+ selection: string,
tokenName?: string,
token?: string
};
/*:: mounted: boolean; */
/*:: props: Props; */
state /*: State */ = {
- loading: false
+ existingToken: '',
+ loading: false,
+ selection: 'generate'
};
componentDidMount() {
this.mounted = false;
}
+ getToken = () =>
+ this.state.selection === 'generate' ? this.state.token : this.state.existingToken;
+
handleTokenNameChange = (event /*: { target: HTMLInputElement } */) => {
this.setState({ tokenName: event.target.value });
};
handleContinueClick = (event /*: Event */) => {
event.preventDefault();
- if (this.state.token) {
- this.props.onContinue(this.state.token);
+ const token = this.getToken();
+ if (token) {
+ this.props.onContinue(token);
}
};
+ handleGenerateClick = (event /*: Event */) => {
+ event.preventDefault();
+ this.setState({ selection: 'generate' });
+ };
+
+ handleUseExistingClick = (event /*: Event */) => {
+ event.preventDefault();
+ this.setState({ selection: 'use-existing' });
+ };
+
+ handleExisingTokenChange = (event /*: { currentTarget: HTMLInputElement } */) => {
+ this.setState({ existingToken: event.currentTarget.value });
+ };
+
+ renderGenerateOption = () => (
+ <div>
+ <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'
+ })}
+ />
+ {translate('onboading.token.generate_token')}
+ </a>
+ {this.state.selection === 'generate' && (
+ <div className="big-spacer-top">
+ <form onSubmit={this.handleTokenGenerate}>
+ <input
+ autoFocus={true}
+ className="input-large spacer-right text-middle"
+ onChange={this.handleTokenNameChange}
+ placeholder={translate('onboading.token.generate_token.placeholder')}
+ required={true}
+ type="text"
+ value={this.state.tokenName || ''}
+ />
+ {this.state.loading ? (
+ <i className="spinner text-middle" />
+ ) : (
+ <button className="text-middle" disabled={!this.state.tokenName}>
+ {translate('onboarding.token.generate')}
+ </button>
+ )}
+ </form>
+ </div>
+ )}
+ </div>
+ );
+
+ renderUseExistingOption = () => (
+ <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'
+ })}
+ />
+ {translate('onboarding.token.use_existing_token')}
+ </a>
+ {this.state.selection === 'use-existing' && (
+ <div className="big-spacer-top">
+ <input
+ autoFocus={true}
+ className="input-large spacer-right text-middle"
+ onChange={this.handleExisingTokenChange}
+ placeholder={translate('onboarding.token.use_existing_token.placeholder')}
+ required={true}
+ type="text"
+ value={this.state.existingToken}
+ />
+ </div>
+ )}
+ </div>
+ );
+
renderForm = () => {
- const { loading, token, tokenName } = this.state;
+ const { existingToken, loading, selection, token, tokenName } = this.state;
return (
<div className="boxed-group-inner">
)}
</form>
) : (
- <form onSubmit={this.handleTokenGenerate}>
- <input
- autoFocus={true}
- className="input-large spacer-right text-middle"
- onChange={this.handleTokenNameChange}
- placeholder={translate('onboarding.token.placeholder')}
- required={true}
- type="text"
- value={tokenName || ''}
- />
- {loading ? (
- <i className="spinner text-middle" />
- ) : (
- <button className="text-middle">{translate('onboarding.token.generate')}</button>
- )}
- </form>
+ <div>
+ {this.renderGenerateOption()}
+ {this.renderUseExistingOption()}
+ </div>
)}
<div className="note big-spacer-top width-50">{translate('onboarding.token.text')}</div>
- {token != null && (
+ {((selection === 'generate' && token != null) ||
+ (selection === 'use-existing' && existingToken)) && (
<div className="big-spacer-top">
<button className="js-continue" onClick={this.handleContinueClick}>
{translate('continue')}
};
renderResult = () => {
- const { token, tokenName } = this.state;
+ const { selection, tokenName } = this.state;
+ const token = this.getToken();
if (!token) {
return null;
return (
<div className="boxed-group-actions">
<i className="icon-check spacer-right" />
- {tokenName}
- {': '}
+ {selection === 'generate' && tokenName && `${tokenName}: `}
<strong>{token}</strong>
</div>
);
click(wrapper.find('.js-continue'));
expect(onContinue).toBeCalledWith('abcd1234');
});
+
+it('uses existing token', () => {
+ const onContinue = jest.fn();
+ const wrapper = mount(
+ <TokenStep
+ finished={false}
+ open={true}
+ onContinue={onContinue}
+ onOpen={jest.fn()}
+ stepNumber={1}
+ />
+ );
+ wrapper.setState({ existingToken: 'abcd1234', selection: 'use-existing' });
+ click(wrapper.find('.js-continue'));
+ expect(onContinue).toBeCalledWith('abcd1234');
+});
<div
className="page-description"
>
- onboarding.header.description_x.2
+ onboarding.header.description.2
</div>
</header>
<TokenStep
<div
className="page-description"
>
- onboarding.header.description_x.2
+ onboarding.header.description.2
</div>
</header>
<TokenStep
<div
className="page-description"
>
- onboarding.header.description_x.3
+ onboarding.header.description.3
</div>
</header>
<OrganizationStep
<div
className="page-description"
>
- onboarding.header.description_x.3
+ onboarding.header.description.3
</div>
</header>
<OrganizationStep
<div
className="page-description"
>
- onboarding.header.description_x.3
+ onboarding.header.description.3
</div>
</header>
<OrganizationStep
<div
className="boxed-group-inner"
>
- <form
- onSubmit={[Function]}
- >
- <input
- autoFocus={true}
- className="input-large spacer-right text-middle"
- onChange={[Function]}
- placeholder="onboarding.token.placeholder"
- required={true}
- type="text"
- value=""
- />
- <button
- className="text-middle"
+ <div>
+ <div>
+ <a
+ className="js-new link-base-color link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="icon-radio spacer-right is-checked"
+ />
+ onboading.token.generate_token
+ </a>
+ <div
+ className="big-spacer-top"
+ >
+ <form
+ onSubmit={[Function]}
+ >
+ <input
+ autoFocus={true}
+ className="input-large spacer-right text-middle"
+ onChange={[Function]}
+ placeholder="onboading.token.generate_token.placeholder"
+ required={true}
+ type="text"
+ value=""
+ />
+ <button
+ className="text-middle"
+ disabled={true}
+ >
+ onboarding.token.generate
+ </button>
+ </form>
+ </div>
+ </div>
+ <div
+ className="big-spacer-top"
>
- onboarding.token.generate
- </button>
- </form>
+ <a
+ className="js-new link-base-color link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="icon-radio spacer-right"
+ />
+ onboarding.token.use_existing_token
+ </a>
+ </div>
+ </div>
<div
className="note big-spacer-top width-50"
>
<div
className="boxed-group-inner"
>
- <form
- onSubmit={[Function]}
- >
- <input
- autoFocus={true}
- className="input-large spacer-right text-middle"
- onChange={[Function]}
- placeholder="onboarding.token.placeholder"
- required={true}
- type="text"
- value="my token"
- />
- <i
- className="spinner text-middle"
- />
- </form>
+ <div>
+ <div>
+ <a
+ className="js-new link-base-color link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="icon-radio spacer-right is-checked"
+ />
+ onboading.token.generate_token
+ </a>
+ <div
+ className="big-spacer-top"
+ >
+ <form
+ onSubmit={[Function]}
+ >
+ <input
+ autoFocus={true}
+ className="input-large spacer-right text-middle"
+ onChange={[Function]}
+ placeholder="onboading.token.generate_token.placeholder"
+ required={true}
+ type="text"
+ value="my token"
+ />
+ <i
+ className="spinner text-middle"
+ />
+ </form>
+ </div>
+ </div>
+ <div
+ className="big-spacer-top"
+ >
+ <a
+ className="js-new link-base-color link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="icon-radio spacer-right"
+ />
+ onboarding.token.use_existing_token
+ </a>
+ </div>
+ </div>
<div
className="note big-spacer-top width-50"
>
<div
className="boxed-group-inner"
>
- <form
- onSubmit={[Function]}
- >
- <input
- autoFocus={true}
- className="input-large spacer-right text-middle"
- onChange={[Function]}
- placeholder="onboarding.token.placeholder"
- required={true}
- type="text"
- value=""
- />
- <button
- className="text-middle"
+ <div>
+ <div>
+ <a
+ className="js-new link-base-color link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="icon-radio spacer-right is-checked"
+ />
+ onboading.token.generate_token
+ </a>
+ <div
+ className="big-spacer-top"
+ >
+ <form
+ onSubmit={[Function]}
+ >
+ <input
+ autoFocus={true}
+ className="input-large spacer-right text-middle"
+ onChange={[Function]}
+ placeholder="onboading.token.generate_token.placeholder"
+ required={true}
+ type="text"
+ value=""
+ />
+ <button
+ className="text-middle"
+ disabled={true}
+ >
+ onboarding.token.generate
+ </button>
+ </form>
+ </div>
+ </div>
+ <div
+ className="big-spacer-top"
>
- onboarding.token.generate
- </button>
- </form>
+ <a
+ className="js-new link-base-color link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="icon-radio spacer-right"
+ />
+ onboarding.token.use_existing_token
+ </a>
+ </div>
+ </div>
<div
className="note big-spacer-top width-50"
>
onboarding.header.sonarcloud=Welcome to SonarCloud!
onboarding.header.description=Want to quickly analyze a first project? Follow these {0} easy steps.
-onboarding.token.header=Generate a token
+onboarding.token.header=Provide a token
onboarding.token.text=The token is used to identify you when an analysis is performed. If it has been compromised, you can revoke it at any point of time in your user account.
onboarding.token.generate=Generate
onboarding.token.placeholder=Enter a name for your token
+onboading.token.generate_token=Generate a token
+onboading.token.generate_token.placeholder=Enter a name for your token
+onboarding.token.use_existing_token=Use existing token
+onboarding.token.use_existing_token.placeholder=Enter your existing token
onboarding.organization.header=Choose an organization for your project
onboarding.organization.text=Organizations are where your projects belong. You can add your team members to your organization later to allow them to contribute to your projects.