@@ -25,9 +25,11 @@ import GlobalNavMenu from './GlobalNavMenu'; | |||
import GlobalNavUserContainer from './GlobalNavUserContainer'; | |||
import Search from '../../search/Search'; | |||
import GlobalHelp from '../../help/GlobalHelp'; | |||
import Tooltip from '../../../../components/controls/Tooltip'; | |||
import HelpIcon from '../../../../components/icons-components/HelpIcon'; | |||
import OnboardingModal from '../../../../apps/tutorials/onboarding/OnboardingModal'; | |||
import { getCurrentUser, getAppState, getSettingValue } from '../../../../store/rootReducer'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
appState: { organizationsEnabled: boolean }, | |||
@@ -37,12 +39,18 @@ type Props = { | |||
type State = { | |||
helpOpen: boolean, | |||
onboardingTutorialOpen: boolean | |||
onboardingTutorialOpen: boolean, | |||
onboardingTutorialTooltip: boolean | |||
}; | |||
class GlobalNav extends React.PureComponent { | |||
interval: ?number; | |||
props: Props; | |||
state: State = { helpOpen: false, onboardingTutorialOpen: false }; | |||
state: State = { | |||
helpOpen: false, | |||
onboardingTutorialOpen: false, | |||
onboardingTutorialTooltip: false | |||
}; | |||
componentDidMount() { | |||
window.addEventListener('keypress', this.onKeyPress); | |||
@@ -52,6 +60,9 @@ class GlobalNav extends React.PureComponent { | |||
} | |||
componentWillUnmount() { | |||
if (this.interval) { | |||
clearInterval(this.interval); | |||
} | |||
window.removeEventListener('keypress', this.onKeyPress); | |||
} | |||
@@ -76,7 +87,14 @@ class GlobalNav extends React.PureComponent { | |||
openOnboardingTutorial = () => this.setState({ helpOpen: false, onboardingTutorialOpen: true }); | |||
closeOnboardingTutorial = () => this.setState({ onboardingTutorialOpen: false }); | |||
finishOnboardingTutorial = () => this.setState({ onboardingTutorialOpen: false }); | |||
skipOnboardingTutorial = () => { | |||
this.setState({ onboardingTutorialOpen: false, onboardingTutorialTooltip: true }); | |||
this.interval = setInterval(() => { | |||
this.setState({ onboardingTutorialTooltip: false }); | |||
}, 3000); | |||
}; | |||
render() { | |||
return ( | |||
@@ -90,7 +108,14 @@ class GlobalNav extends React.PureComponent { | |||
<Search appState={this.props.appState} currentUser={this.props.currentUser} /> | |||
<li> | |||
<a className="navbar-help" onClick={this.handleHelpClick} href="#"> | |||
<HelpIcon /> | |||
{this.state.onboardingTutorialTooltip | |||
? <Tooltip | |||
defaultVisible={true} | |||
overlay={translate('tutorials.follow_later')} | |||
trigger="manual"> | |||
<HelpIcon /> | |||
</Tooltip> | |||
: <HelpIcon />} | |||
</a> | |||
</li> | |||
<GlobalNavUserContainer {...this.props} /> | |||
@@ -106,7 +131,10 @@ class GlobalNav extends React.PureComponent { | |||
/>} | |||
{this.state.onboardingTutorialOpen && | |||
<OnboardingModal onClose={this.closeOnboardingTutorial} />} | |||
<OnboardingModal | |||
onFinish={this.finishOnboardingTutorial} | |||
onSkip={this.skipOnboardingTutorial} | |||
/>} | |||
</nav> | |||
); | |||
} |
@@ -50,7 +50,8 @@ export default class AnalysisStep extends React.PureComponent { | |||
handleLanguageSelect = (result?: Result) => { | |||
this.setState({ result }); | |||
this.props.onFinish(result && result.projectKey); | |||
const projectKey = result && result.language !== 'java' ? result.projectKey : undefined; | |||
this.props.onFinish(projectKey); | |||
}; | |||
handleLanguageReset = () => { | |||
@@ -174,6 +175,8 @@ export default class AnalysisStep extends React.PureComponent { | |||
render() { | |||
return ( | |||
<Step | |||
finished={false} | |||
onOpen={() => {}} | |||
open={this.props.open} | |||
renderForm={this.renderForm} | |||
renderResult={this.renderResult} |
@@ -20,6 +20,7 @@ | |||
// @flow | |||
import React from 'react'; | |||
import { debounce } from 'lodash'; | |||
import CloseIcon from '../../../components/icons-components/CloseIcon'; | |||
import { | |||
createOrganization, | |||
deleteOrganization, | |||
@@ -124,9 +125,9 @@ export default class NewOrganizationForm extends React.PureComponent { | |||
? <form onSubmit={this.handleOrganizationDelete}> | |||
<span className="spacer-right text-middle">{organization}</span> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean"> | |||
<i className="icon-delete" /> | |||
? <i className="spinner text-middle" /> | |||
: <button className="button-clean text-middle"> | |||
<CloseIcon className="icon-red" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleOrganizationCreate}> | |||
@@ -142,7 +143,7 @@ export default class NewOrganizationForm extends React.PureComponent { | |||
value={organization} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
? <i className="spinner text-middle" /> | |||
: <button className="text-middle" disabled={!valid}>{translate('create')}</button>} | |||
{!unique && | |||
<span className="big-spacer-left text-danger text-middle"> |
@@ -19,6 +19,7 @@ | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import CloseIcon from '../../../components/icons-components/CloseIcon'; | |||
import { createProject, deleteProject } from '../../../api/components'; | |||
import { translate } from '../../../helpers/l10n'; | |||
@@ -109,9 +110,9 @@ export default class NewProjectForm extends React.PureComponent { | |||
? <form onSubmit={this.handleProjectDelete}> | |||
<span className="spacer-right text-middle">{projectKey}</span> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean"> | |||
<i className="icon-delete" /> | |||
? <i className="spinner text-middle" /> | |||
: <button className="button-clean text-middle"> | |||
<CloseIcon className="icon-red" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleProjectCreate}> | |||
@@ -126,7 +127,7 @@ export default class NewProjectForm extends React.PureComponent { | |||
value={projectKey} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
? <i className="spinner text-middle" /> | |||
: <button className="text-middle" disabled={!valid}>{translate('Done')}</button>} | |||
<div className="note spacer-top abs-width-300"> | |||
{translate('onboarding.project_key_requirement')} |
@@ -19,6 +19,7 @@ | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Helmet from 'react-helmet'; | |||
import TokenStep from './TokenStep'; | |||
import OrganizationStep from './OrganizationStep'; | |||
import AnalysisStep from './AnalysisStep'; | |||
@@ -29,12 +30,13 @@ import { getProjectUrl } from '../../../helpers/urls'; | |||
import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; | |||
import './styles.css'; | |||
type Props = { | |||
type Props = {| | |||
currentUser: { login: string, isLoggedIn: boolean }, | |||
onFinish: () => void, | |||
onSkip: () => void, | |||
organizationsEnabled: boolean, | |||
sonarCloud: boolean | |||
}; | |||
|}; | |||
type State = { | |||
finished: boolean, | |||
@@ -74,12 +76,16 @@ export default class Onboarding extends React.PureComponent { | |||
this.mounted = false; | |||
} | |||
finishOnboarding = () => { | |||
finishOnboarding = (skipped: boolean = false) => { | |||
this.setState({ skipping: true }); | |||
skipOnboarding().then( | |||
() => { | |||
if (this.mounted) { | |||
this.props.onSkip(); | |||
if (skipped) { | |||
this.props.onSkip(); | |||
} else { | |||
this.props.onFinish(); | |||
} | |||
if (this.state.projectKey) { | |||
this.context.router.push(getProjectUrl(this.state.projectKey)); | |||
@@ -107,9 +113,13 @@ export default class Onboarding extends React.PureComponent { | |||
this.setState({ organization, step: 'token' }); | |||
}; | |||
handleTokenOpen = () => this.setState({ step: 'token' }); | |||
handleOrganizationOpen = () => this.setState({ step: 'organization' }); | |||
handleSkipClick = (event: Event) => { | |||
event.preventDefault(); | |||
this.finishOnboarding(); | |||
this.finishOnboarding(true); | |||
}; | |||
handleFinish = (projectKey?: string) => this.setState({ finished: true, projectKey }); | |||
@@ -126,61 +136,69 @@ export default class Onboarding extends React.PureComponent { | |||
let stepNumber = 1; | |||
const header = translate(sonarCloud ? 'onboarding.header.sonarcloud' : 'onboarding.header'); | |||
return ( | |||
<div className="page page-limited"> | |||
<header className="page-header"> | |||
<h1 className="page-title"> | |||
{translate(sonarCloud ? 'onboarding.header.sonarcloud' : 'onboarding.header')} | |||
</h1> | |||
<div className="page-actions"> | |||
{this.state.skipping | |||
? <i className="spinner" /> | |||
: <a className="js-skip text-muted" href="#" onClick={this.handleSkipClick}> | |||
{translate('tutorials.skip')} | |||
</a>} | |||
</div> | |||
<div className="page-description"> | |||
{translate('onboarding.header.description')} | |||
</div> | |||
</header> | |||
{organizationsEnabled && | |||
<OrganizationStep | |||
currentUser={this.props.currentUser} | |||
onContinue={this.handleOrganizationDone} | |||
open={step === 'organization'} | |||
<div className="modal-container"> | |||
<Helmet title={header} titleTemplate="%s" /> | |||
<div className="page page-limited onboarding"> | |||
<header className="page-header"> | |||
<h1 className="page-title">{header}</h1> | |||
<div className="page-actions"> | |||
{this.state.skipping | |||
? <i className="spinner" /> | |||
: <a className="js-skip text-muted" href="#" onClick={this.handleSkipClick}> | |||
{translate('tutorials.skip')} | |||
</a>} | |||
</div> | |||
<div className="page-description"> | |||
{translate('onboarding.header.description')} | |||
</div> | |||
</header> | |||
{organizationsEnabled && | |||
<OrganizationStep | |||
currentUser={this.props.currentUser} | |||
finished={this.state.organization != null} | |||
onContinue={this.handleOrganizationDone} | |||
onOpen={this.handleOrganizationOpen} | |||
open={step === 'organization'} | |||
stepNumber={stepNumber++} | |||
/>} | |||
<TokenStep | |||
finished={this.state.token != null} | |||
onContinue={this.handleTokenDone} | |||
onOpen={this.handleTokenOpen} | |||
open={step === 'token'} | |||
stepNumber={stepNumber++} | |||
/>} | |||
<TokenStep | |||
onContinue={this.handleTokenDone} | |||
open={step === 'token'} | |||
stepNumber={stepNumber++} | |||
/> | |||
<AnalysisStep | |||
onFinish={this.handleFinish} | |||
onReset={this.handleReset} | |||
organization={this.state.organization} | |||
open={step === 'analysis'} | |||
sonarCloud={sonarCloud} | |||
stepNumber={stepNumber} | |||
token={token} | |||
/> | |||
{this.state.finished && | |||
!this.state.skipping && | |||
(this.state.projectKey | |||
? <ProjectWatcher | |||
onFinish={this.finishOnboarding} | |||
onTimeout={this.handleTimeout} | |||
projectKey={this.state.projectKey} | |||
/> | |||
: <footer className="text-right"> | |||
<a className="button" href="#" onClick={this.handleSkipClick}> | |||
{translate('tutorials.finish')} | |||
</a> | |||
</footer>)} | |||
/> | |||
<AnalysisStep | |||
onFinish={this.handleFinish} | |||
onReset={this.handleReset} | |||
organization={this.state.organization} | |||
open={step === 'analysis'} | |||
sonarCloud={sonarCloud} | |||
stepNumber={stepNumber} | |||
token={token} | |||
/> | |||
{this.state.finished && | |||
!this.state.skipping && | |||
(this.state.projectKey | |||
? <ProjectWatcher | |||
onFinish={this.finishOnboarding} | |||
onTimeout={this.handleTimeout} | |||
projectKey={this.state.projectKey} | |||
/> | |||
: <footer className="text-right"> | |||
<a className="button" href="#" onClick={this.handleSkipClick}> | |||
{translate('tutorials.finish')} | |||
</a> | |||
</footer>)} | |||
</div> | |||
</div> | |||
); | |||
} |
@@ -22,9 +22,10 @@ import React from 'react'; | |||
import Modal from 'react-modal'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
onClose: () => void | |||
}; | |||
type Props = {| | |||
onFinish: () => void, | |||
onSkip: () => void | |||
|}; | |||
type State = { | |||
OnboardingContainer?: Object | |||
@@ -60,9 +61,10 @@ export default class OnboardingModal extends React.PureComponent { | |||
<Modal | |||
isOpen={true} | |||
contentLabel={translate('tutorials.onboarding')} | |||
className="modal modal-full-screen" | |||
className="modal modal-large" | |||
overlayClassName="modal-overlay"> | |||
{OnboardingContainer != null && <OnboardingContainer onSkip={this.props.onClose} />} | |||
{OnboardingContainer != null && | |||
<OnboardingContainer onFinish={this.props.onFinish} onSkip={this.props.onSkip} />} | |||
</Modal> | |||
); | |||
} |
@@ -27,11 +27,14 @@ import NewOrganizationForm from './NewOrganizationForm'; | |||
import { getMyOrganizations } from '../../../api/organizations'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
type Props = {| | |||
currentUser: { login: string, isLoggedIn: boolean }, | |||
finished: boolean, | |||
onOpen: () => void, | |||
onContinue: (organization: string) => void, | |||
open: boolean, | |||
onContinue: (organization: string) => void | |||
}; | |||
stepNumber: number | |||
|}; | |||
type State = { | |||
loading: boolean, | |||
@@ -229,10 +232,12 @@ export default class OrganizationStep extends React.PureComponent { | |||
render() { | |||
return ( | |||
<Step | |||
finished={this.props.finished} | |||
onOpen={this.props.onOpen} | |||
open={this.props.open} | |||
renderForm={this.renderForm} | |||
renderResult={this.renderResult} | |||
stepNumber={1} | |||
stepNumber={this.props.stepNumber} | |||
stepTitle={translate('onboarding.organization.header')} | |||
/> | |||
); |
@@ -21,21 +21,35 @@ | |||
import React from 'react'; | |||
import classNames from 'classnames'; | |||
type Props = { | |||
type Props = {| | |||
finished: boolean, | |||
onOpen: () => void, | |||
open: boolean, | |||
renderForm: () => React.Element<*>, | |||
renderResult: () => ?React.Element<*>, | |||
stepNumber: number, | |||
stepTitle: string | |||
}; | |||
|}; | |||
export default function Step(props: Props) { | |||
const className = classNames('boxed-group', 'onboarding-step', { | |||
'onboarding-step-open': props.open | |||
'is-open': props.open, | |||
'is-finished': props.finished | |||
}); | |||
const clickable = !props.open && props.finished; | |||
const handleClick = (event: Event) => { | |||
event.preventDefault; | |||
props.onOpen(); | |||
}; | |||
return ( | |||
<div className={className}> | |||
<div | |||
className={className} | |||
onClick={clickable ? handleClick : undefined} | |||
role={clickable ? 'button' : undefined} | |||
tabIndex={clickable ? 0 : undefined}> | |||
<div className="onboarding-step-number">{props.stepNumber}</div> | |||
{!props.open && props.renderResult()} | |||
<div className="boxed-group-header"> |
@@ -20,14 +20,17 @@ | |||
// @flow | |||
import React from 'react'; | |||
import Step from './Step'; | |||
import CloseIcon from '../../../components/icons-components/CloseIcon'; | |||
import { generateToken, revokeToken } from '../../../api/user-tokens'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
type Props = {| | |||
finished: boolean, | |||
open: boolean, | |||
onContinue: (token: string) => void, | |||
onOpen: () => void, | |||
stepNumber: number | |||
}; | |||
|}; | |||
type State = { | |||
loading: boolean, | |||
@@ -38,11 +41,6 @@ type State = { | |||
export default class TokenStep extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
static defaultProps = { | |||
stepNumber: 1 | |||
}; | |||
state: State = { | |||
loading: false | |||
}; | |||
@@ -111,24 +109,20 @@ export default class TokenStep extends React.PureComponent { | |||
return ( | |||
<div className="boxed-group-inner"> | |||
<div className="big-spacer-bottom width-50"> | |||
{translate('onboarding.token.text')} | |||
</div> | |||
{token != null | |||
? <form onSubmit={this.handleTokenRevoke}> | |||
{tokenName}{': '} | |||
<span className="monospaced spacer-right">{token}</span> | |||
<span className="text-middle">{tokenName}{': '}</span> | |||
<strong className="spacer-right text-middle">{token}</strong> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean" onClick={this.handleTokenRevoke}> | |||
<i className="icon-delete" /> | |||
? <i className="spinner text-middle" /> | |||
: <button className="button-clean text-middle" onClick={this.handleTokenRevoke}> | |||
<CloseIcon className="icon-red" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleTokenGenerate}> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
className="input-large spacer-right text-middle" | |||
onChange={this.handleTokenNameChange} | |||
placeholder={translate('onboarding.token.placeholder')} | |||
required={true} | |||
@@ -136,10 +130,14 @@ export default class TokenStep extends React.PureComponent { | |||
value={tokenName || ''} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button>{translate('onboarding.token.generate')}</button>} | |||
? <i className="spinner text-middle" /> | |||
: <button className="text-middle">{translate('onboarding.token.generate')}</button>} | |||
</form>} | |||
<div className="note big-spacer-top width-50"> | |||
{translate('onboarding.token.text')} | |||
</div> | |||
{token != null && | |||
<div className="big-spacer-top"> | |||
<button className="js-continue" onClick={this.handleContinueClick}> | |||
@@ -161,7 +159,7 @@ export default class TokenStep extends React.PureComponent { | |||
<div className="boxed-group-actions"> | |||
<i className="icon-check spacer-right" /> | |||
{tokenName}{': '} | |||
<strong className="monospaced">{token}</strong> | |||
<strong>{token}</strong> | |||
</div> | |||
); | |||
}; | |||
@@ -169,6 +167,8 @@ export default class TokenStep extends React.PureComponent { | |||
render() { | |||
return ( | |||
<Step | |||
finished={this.props.finished} | |||
onOpen={this.props.onOpen} | |||
open={this.props.open} | |||
renderForm={this.renderForm} | |||
renderResult={this.renderResult} |
@@ -33,6 +33,7 @@ it('guides for on-premise', () => { | |||
const wrapper = shallow( | |||
<Onboarding | |||
currentUser={currentUser} | |||
onFinish={jest.fn()} | |||
onSkip={jest.fn()} | |||
organizationsEnabled={false} | |||
sonarCloud={false} | |||
@@ -50,6 +51,7 @@ it('guides for sonarcloud', () => { | |||
const wrapper = shallow( | |||
<Onboarding | |||
currentUser={currentUser} | |||
onFinish={jest.fn()} | |||
onSkip={jest.fn()} | |||
organizationsEnabled={true} | |||
sonarCloud={true} | |||
@@ -73,6 +75,7 @@ it('skips', () => { | |||
const wrapper = mount( | |||
<Onboarding | |||
currentUser={currentUser} | |||
onFinish={jest.fn()} | |||
onSkip={onSkip} | |||
organizationsEnabled={false} | |||
sonarCloud={false} |
@@ -32,7 +32,14 @@ const currentUser = { isLoggedIn: true, login: 'user' }; | |||
it('works with personal organization', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep currentUser={currentUser} onContinue={onContinue} open={true} /> | |||
<OrganizationStep | |||
currentUser={currentUser} | |||
finished={false} | |||
onContinue={onContinue} | |||
onOpen={jest.fn()} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('user'); | |||
@@ -41,7 +48,14 @@ it('works with personal organization', () => { | |||
it('works with existing organization', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep currentUser={currentUser} onContinue={onContinue} open={true} /> | |||
<OrganizationStep | |||
currentUser={currentUser} | |||
finished={false} | |||
onContinue={onContinue} | |||
onOpen={jest.fn()} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
); | |||
return doAsync(() => { | |||
click(wrapper.find('.js-existing')); | |||
@@ -54,7 +68,14 @@ it('works with existing organization', () => { | |||
it('works with new organization', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep currentUser={currentUser} onContinue={onContinue} open={true} /> | |||
<OrganizationStep | |||
currentUser={currentUser} | |||
finished={false} | |||
onContinue={onContinue} | |||
onOpen={jest.fn()} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
); | |||
click(wrapper.find('.js-new')); | |||
wrapper.find('NewOrganizationForm').prop('onDone')('new'); |
@@ -21,10 +21,13 @@ | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Step from '../Step'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
it('renders', () => { | |||
const wrapper = shallow( | |||
<Step | |||
finished={true} | |||
onOpen={jest.fn()} | |||
open={true} | |||
renderForm={() => <div>form</div>} | |||
renderResult={() => <div>result</div>} | |||
@@ -36,3 +39,20 @@ it('renders', () => { | |||
wrapper.setProps({ open: false }); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('re-opens', () => { | |||
const onOpen = jest.fn(); | |||
const wrapper = shallow( | |||
<Step | |||
finished={true} | |||
onOpen={onOpen} | |||
open={false} | |||
renderForm={() => <div>form</div>} | |||
renderResult={() => <div>result</div>} | |||
stepNumber={1} | |||
stepTitle="First Step" | |||
/> | |||
); | |||
click(wrapper); | |||
expect(onOpen).toBeCalled(); | |||
}); |
@@ -29,7 +29,15 @@ jest.mock('../../../../api/user-tokens', () => ({ | |||
})); | |||
it('generates token', () => { | |||
const wrapper = mount(<TokenStep open={true} onContinue={jest.fn()} />); | |||
const wrapper = mount( | |||
<TokenStep | |||
finished={false} | |||
open={true} | |||
onContinue={jest.fn()} | |||
onOpen={jest.fn()} | |||
stepNumber={1} | |||
/> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'my token'); | |||
submit(wrapper.find('form')); | |||
@@ -38,7 +46,15 @@ it('generates token', () => { | |||
}); | |||
it('revokes token', () => { | |||
const wrapper = mount(<TokenStep open={true} onContinue={jest.fn()} />); | |||
const wrapper = mount( | |||
<TokenStep | |||
finished={false} | |||
open={true} | |||
onContinue={jest.fn()} | |||
onOpen={jest.fn()} | |||
stepNumber={1} | |||
/> | |||
); | |||
wrapper.setState({ token: 'abcd1234', tokenName: 'my token' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
@@ -48,7 +64,15 @@ it('revokes token', () => { | |||
it('continues', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount(<TokenStep open={true} onContinue={onContinue} />); | |||
const wrapper = mount( | |||
<TokenStep | |||
finished={false} | |||
open={true} | |||
onContinue={onContinue} | |||
onOpen={jest.fn()} | |||
stepNumber={1} | |||
/> | |||
); | |||
wrapper.setState({ token: 'abcd1234', tokenName: 'my token' }); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('abcd1234'); |
@@ -54,7 +54,7 @@ exports[`creates new organization 2`] = ` | |||
value="foo" | |||
/> | |||
<i | |||
className="spinner" | |||
className="spinner text-middle" | |||
/> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
@@ -79,11 +79,24 @@ exports[`creates new organization 3`] = ` | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
className="button-clean text-middle" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
<CloseIcon | |||
className="icon-red" | |||
> | |||
<svg | |||
className="icon-red" | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} | |||
xmlns="http://www.w3.org/2000/svg" | |||
> | |||
<path | |||
d="M12.843 11.232q0 0.357-0.25 0.607l-1.214 1.214q-0.25 0.25-0.607 0.25t-0.607-0.25l-2.625-2.625-2.625 2.625q-0.25 0.25-0.607 0.25t-0.607-0.25l-1.214-1.214q-0.25-0.25-0.25-0.607t0.25-0.607l2.625-2.625-2.625-2.625q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.625 2.625-2.625q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607t-0.25 0.607l-2.625 2.625 2.625 2.625q0.25 0.25 0.25 0.607z" | |||
fill="currentColor" | |||
/> | |||
</svg> | |||
</CloseIcon> | |||
</button> | |||
</form> | |||
</NewOrganizationForm> | |||
@@ -103,11 +116,24 @@ exports[`deletes organization 1`] = ` | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
className="button-clean text-middle" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
<CloseIcon | |||
className="icon-red" | |||
> | |||
<svg | |||
className="icon-red" | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} | |||
xmlns="http://www.w3.org/2000/svg" | |||
> | |||
<path | |||
d="M12.843 11.232q0 0.357-0.25 0.607l-1.214 1.214q-0.25 0.25-0.607 0.25t-0.607-0.25l-2.625-2.625-2.625 2.625q-0.25 0.25-0.607 0.25t-0.607-0.25l-1.214-1.214q-0.25-0.25-0.25-0.607t0.25-0.607l2.625-2.625-2.625-2.625q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.625 2.625-2.625q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607t-0.25 0.607l-2.625 2.625 2.625 2.625q0.25 0.25 0.25 0.607z" | |||
fill="currentColor" | |||
/> | |||
</svg> | |||
</CloseIcon> | |||
</button> | |||
</form> | |||
</NewOrganizationForm> | |||
@@ -127,7 +153,7 @@ exports[`deletes organization 2`] = ` | |||
foo | |||
</span> | |||
<i | |||
className="spinner" | |||
className="spinner text-middle" | |||
/> | |||
</form> | |||
</NewOrganizationForm> |
@@ -69,7 +69,7 @@ exports[`creates new project 2`] = ` | |||
value="foo" | |||
/> | |||
<i | |||
className="spinner" | |||
className="spinner text-middle" | |||
/> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
@@ -103,11 +103,24 @@ exports[`creates new project 3`] = ` | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
className="button-clean text-middle" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
<CloseIcon | |||
className="icon-red" | |||
> | |||
<svg | |||
className="icon-red" | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} | |||
xmlns="http://www.w3.org/2000/svg" | |||
> | |||
<path | |||
d="M12.843 11.232q0 0.357-0.25 0.607l-1.214 1.214q-0.25 0.25-0.607 0.25t-0.607-0.25l-2.625-2.625-2.625 2.625q-0.25 0.25-0.607 0.25t-0.607-0.25l-1.214-1.214q-0.25-0.25-0.25-0.607t0.25-0.607l2.625-2.625-2.625-2.625q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.625 2.625-2.625q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607t-0.25 0.607l-2.625 2.625 2.625 2.625q0.25 0.25 0.25 0.607z" | |||
fill="currentColor" | |||
/> | |||
</svg> | |||
</CloseIcon> | |||
</button> | |||
</form> | |||
</div> | |||
@@ -136,11 +149,24 @@ exports[`deletes project 1`] = ` | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
className="button-clean text-middle" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
<CloseIcon | |||
className="icon-red" | |||
> | |||
<svg | |||
className="icon-red" | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} | |||
xmlns="http://www.w3.org/2000/svg" | |||
> | |||
<path | |||
d="M12.843 11.232q0 0.357-0.25 0.607l-1.214 1.214q-0.25 0.25-0.607 0.25t-0.607-0.25l-2.625-2.625-2.625 2.625q-0.25 0.25-0.607 0.25t-0.607-0.25l-1.214-1.214q-0.25-0.25-0.25-0.607t0.25-0.607l2.625-2.625-2.625-2.625q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.625 2.625-2.625q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607t-0.25 0.607l-2.625 2.625 2.625 2.625q0.25 0.25 0.25 0.607z" | |||
fill="currentColor" | |||
/> | |||
</svg> | |||
</CloseIcon> | |||
</button> | |||
</form> | |||
</div> | |||
@@ -169,7 +195,7 @@ exports[`deletes project 2`] = ` | |||
foo | |||
</span> | |||
<i | |||
className="spinner" | |||
className="spinner text-middle" | |||
/> | |||
</form> | |||
</div> |
@@ -2,257 +2,313 @@ | |||
exports[`guides for on-premise 1`] = ` | |||
<div | |||
className="page page-limited" | |||
className="modal-container" | |||
> | |||
<header | |||
className="page-header" | |||
<HelmetWrapper | |||
title="onboarding.header" | |||
titleTemplate="%s" | |||
/> | |||
<div | |||
className="page page-limited onboarding" | |||
> | |||
<h1 | |||
className="page-title" | |||
> | |||
onboarding.header | |||
</h1> | |||
<div | |||
className="page-actions" | |||
<header | |||
className="page-header" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
<h1 | |||
className="page-title" | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={false} | |||
sonarCloud={false} | |||
stepNumber={2} | |||
/> | |||
onboarding.header | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={false} | |||
sonarCloud={false} | |||
stepNumber={2} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`guides for on-premise 2`] = ` | |||
<div | |||
className="page page-limited" | |||
className="modal-container" | |||
> | |||
<header | |||
className="page-header" | |||
<HelmetWrapper | |||
title="onboarding.header" | |||
titleTemplate="%s" | |||
/> | |||
<div | |||
className="page page-limited onboarding" | |||
> | |||
<h1 | |||
className="page-title" | |||
<header | |||
className="page-header" | |||
> | |||
onboarding.header | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
<h1 | |||
className="page-title" | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={false} | |||
stepNumber={1} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={true} | |||
sonarCloud={false} | |||
stepNumber={2} | |||
token="abcd1234" | |||
/> | |||
onboarding.header | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<TokenStep | |||
finished={true} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={false} | |||
stepNumber={1} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={true} | |||
sonarCloud={false} | |||
stepNumber={2} | |||
token="abcd1234" | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`guides for sonarcloud 1`] = ` | |||
<div | |||
className="page page-limited" | |||
className="modal-container" | |||
> | |||
<header | |||
className="page-header" | |||
<HelmetWrapper | |||
title="onboarding.header.sonarcloud" | |||
titleTemplate="%s" | |||
/> | |||
<div | |||
className="page page-limited onboarding" | |||
> | |||
<h1 | |||
className="page-title" | |||
<header | |||
className="page-header" | |||
> | |||
onboarding.header.sonarcloud | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
<h1 | |||
className="page-title" | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<OrganizationStep | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
"login": "admin", | |||
onboarding.header.sonarcloud | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<OrganizationStep | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
"login": "admin", | |||
} | |||
} | |||
} | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={false} | |||
stepNumber={2} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={false} | |||
sonarCloud={true} | |||
stepNumber={3} | |||
/> | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
/> | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={false} | |||
stepNumber={2} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={false} | |||
sonarCloud={true} | |||
stepNumber={3} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`guides for sonarcloud 2`] = ` | |||
<div | |||
className="page page-limited" | |||
className="modal-container" | |||
> | |||
<header | |||
className="page-header" | |||
<HelmetWrapper | |||
title="onboarding.header.sonarcloud" | |||
titleTemplate="%s" | |||
/> | |||
<div | |||
className="page page-limited onboarding" | |||
> | |||
<h1 | |||
className="page-title" | |||
> | |||
onboarding.header.sonarcloud | |||
</h1> | |||
<div | |||
className="page-actions" | |||
<header | |||
className="page-header" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
<h1 | |||
className="page-title" | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<OrganizationStep | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
"login": "admin", | |||
onboarding.header.sonarcloud | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<OrganizationStep | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
"login": "admin", | |||
} | |||
} | |||
} | |||
onContinue={[Function]} | |||
open={false} | |||
stepNumber={1} | |||
/> | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={2} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={false} | |||
organization="my-org" | |||
sonarCloud={true} | |||
stepNumber={3} | |||
/> | |||
finished={true} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={false} | |||
stepNumber={1} | |||
/> | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={2} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={false} | |||
organization="my-org" | |||
sonarCloud={true} | |||
stepNumber={3} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`guides for sonarcloud 3`] = ` | |||
<div | |||
className="page page-limited" | |||
className="modal-container" | |||
> | |||
<header | |||
className="page-header" | |||
<HelmetWrapper | |||
title="onboarding.header.sonarcloud" | |||
titleTemplate="%s" | |||
/> | |||
<div | |||
className="page page-limited onboarding" | |||
> | |||
<h1 | |||
className="page-title" | |||
> | |||
onboarding.header.sonarcloud | |||
</h1> | |||
<div | |||
className="page-actions" | |||
<header | |||
className="page-header" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
<h1 | |||
className="page-title" | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<OrganizationStep | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
"login": "admin", | |||
onboarding.header.sonarcloud | |||
</h1> | |||
<div | |||
className="page-actions" | |||
> | |||
<a | |||
className="js-skip text-muted" | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
tutorials.skip | |||
</a> | |||
</div> | |||
<div | |||
className="page-description" | |||
> | |||
onboarding.header.description | |||
</div> | |||
</header> | |||
<OrganizationStep | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
"login": "admin", | |||
} | |||
} | |||
} | |||
onContinue={[Function]} | |||
open={false} | |||
stepNumber={1} | |||
/> | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={false} | |||
stepNumber={2} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={true} | |||
organization="my-org" | |||
sonarCloud={true} | |||
stepNumber={3} | |||
token="abcd1234" | |||
/> | |||
finished={true} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={false} | |||
stepNumber={1} | |||
/> | |||
<TokenStep | |||
finished={true} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={false} | |||
stepNumber={2} | |||
/> | |||
<AnalysisStep | |||
onFinish={[Function]} | |||
onReset={[Function]} | |||
open={true} | |||
organization="my-org" | |||
sonarCloud={true} | |||
stepNumber={3} | |||
token="abcd1234" | |||
/> | |||
</div> | |||
</div> | |||
`; |
@@ -2,7 +2,7 @@ | |||
exports[`renders 1`] = ` | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open is-finished" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -24,7 +24,10 @@ exports[`renders 1`] = ` | |||
exports[`renders 2`] = ` | |||
<div | |||
className="boxed-group onboarding-step" | |||
className="boxed-group onboarding-step is-finished" | |||
onClick={[Function]} | |||
role="button" | |||
tabIndex={0} | |||
> | |||
<div | |||
className="onboarding-step-number" |
@@ -2,11 +2,15 @@ | |||
exports[`generates token 1`] = ` | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
finished={false} | |||
onOpen={[Function]} | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
@@ -14,7 +18,7 @@ exports[`generates token 1`] = ` | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -31,27 +35,29 @@ exports[`generates token 1`] = ` | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
className="input-large spacer-right text-middle" | |||
onChange={[Function]} | |||
placeholder="onboarding.token.placeholder" | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button> | |||
<button | |||
className="text-middle" | |||
> | |||
onboarding.token.generate | |||
</button> | |||
</form> | |||
<div | |||
className="note big-spacer-top width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
</div> | |||
</div> | |||
</Step> | |||
@@ -60,11 +66,15 @@ exports[`generates token 1`] = ` | |||
exports[`generates token 2`] = ` | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
finished={false} | |||
onOpen={[Function]} | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
@@ -72,7 +82,7 @@ exports[`generates token 2`] = ` | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -89,17 +99,12 @@ exports[`generates token 2`] = ` | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
className="input-large spacer-right text-middle" | |||
onChange={[Function]} | |||
placeholder="onboarding.token.placeholder" | |||
required={true} | |||
@@ -107,9 +112,14 @@ exports[`generates token 2`] = ` | |||
value="my token" | |||
/> | |||
<i | |||
className="spinner" | |||
className="spinner text-middle" | |||
/> | |||
</form> | |||
<div | |||
className="note big-spacer-top width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
</div> | |||
</div> | |||
</Step> | |||
@@ -118,11 +128,15 @@ exports[`generates token 2`] = ` | |||
exports[`generates token 3`] = ` | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
finished={false} | |||
onOpen={[Function]} | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
@@ -130,7 +144,7 @@ exports[`generates token 3`] = ` | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -147,30 +161,47 @@ exports[`generates token 3`] = ` | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
my token | |||
: | |||
<span | |||
className="monospaced spacer-right" | |||
className="text-middle" | |||
> | |||
abcd1234 | |||
my token | |||
: | |||
</span> | |||
<strong | |||
className="spacer-right text-middle" | |||
> | |||
abcd1234 | |||
</strong> | |||
<button | |||
className="button-clean" | |||
className="button-clean text-middle" | |||
onClick={[Function]} | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
<CloseIcon | |||
className="icon-red" | |||
> | |||
<svg | |||
className="icon-red" | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} | |||
xmlns="http://www.w3.org/2000/svg" | |||
> | |||
<path | |||
d="M12.843 11.232q0 0.357-0.25 0.607l-1.214 1.214q-0.25 0.25-0.607 0.25t-0.607-0.25l-2.625-2.625-2.625 2.625q-0.25 0.25-0.607 0.25t-0.607-0.25l-1.214-1.214q-0.25-0.25-0.25-0.607t0.25-0.607l2.625-2.625-2.625-2.625q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.625 2.625-2.625q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607t-0.25 0.607l-2.625 2.625 2.625 2.625q0.25 0.25 0.25 0.607z" | |||
fill="currentColor" | |||
/> | |||
</svg> | |||
</CloseIcon> | |||
</button> | |||
</form> | |||
<div | |||
className="note big-spacer-top width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
@@ -189,11 +220,15 @@ exports[`generates token 3`] = ` | |||
exports[`revokes token 1`] = ` | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
finished={false} | |||
onOpen={[Function]} | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
@@ -201,7 +236,7 @@ exports[`revokes token 1`] = ` | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -218,30 +253,47 @@ exports[`revokes token 1`] = ` | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
my token | |||
: | |||
<span | |||
className="monospaced spacer-right" | |||
className="text-middle" | |||
> | |||
abcd1234 | |||
my token | |||
: | |||
</span> | |||
<strong | |||
className="spacer-right text-middle" | |||
> | |||
abcd1234 | |||
</strong> | |||
<button | |||
className="button-clean" | |||
className="button-clean text-middle" | |||
onClick={[Function]} | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
<CloseIcon | |||
className="icon-red" | |||
> | |||
<svg | |||
className="icon-red" | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} | |||
xmlns="http://www.w3.org/2000/svg" | |||
> | |||
<path | |||
d="M12.843 11.232q0 0.357-0.25 0.607l-1.214 1.214q-0.25 0.25-0.607 0.25t-0.607-0.25l-2.625-2.625-2.625 2.625q-0.25 0.25-0.607 0.25t-0.607-0.25l-1.214-1.214q-0.25-0.25-0.25-0.607t0.25-0.607l2.625-2.625-2.625-2.625q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.625 2.625-2.625q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607t-0.25 0.607l-2.625 2.625 2.625 2.625q0.25 0.25 0.25 0.607z" | |||
fill="currentColor" | |||
/> | |||
</svg> | |||
</CloseIcon> | |||
</button> | |||
</form> | |||
<div | |||
className="note big-spacer-top width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
@@ -260,11 +312,15 @@ exports[`revokes token 1`] = ` | |||
exports[`revokes token 2`] = ` | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
finished={false} | |||
onOpen={[Function]} | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
@@ -272,7 +328,7 @@ exports[`revokes token 2`] = ` | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -289,25 +345,29 @@ exports[`revokes token 2`] = ` | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
my token | |||
: | |||
<span | |||
className="monospaced spacer-right" | |||
className="text-middle" | |||
> | |||
abcd1234 | |||
my token | |||
: | |||
</span> | |||
<strong | |||
className="spacer-right text-middle" | |||
> | |||
abcd1234 | |||
</strong> | |||
<i | |||
className="spinner" | |||
className="spinner text-middle" | |||
/> | |||
</form> | |||
<div | |||
className="note big-spacer-top width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
@@ -326,11 +386,15 @@ exports[`revokes token 2`] = ` | |||
exports[`revokes token 3`] = ` | |||
<TokenStep | |||
finished={false} | |||
onContinue={[Function]} | |||
onOpen={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
finished={false} | |||
onOpen={[Function]} | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
@@ -338,7 +402,7 @@ exports[`revokes token 3`] = ` | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -355,27 +419,29 @@ exports[`revokes token 3`] = ` | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
className="input-large spacer-right text-middle" | |||
onChange={[Function]} | |||
placeholder="onboarding.token.placeholder" | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button> | |||
<button | |||
className="text-middle" | |||
> | |||
onboarding.token.generate | |||
</button> | |||
</form> | |||
<div | |||
className="note big-spacer-top width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
</div> | |||
</div> | |||
</Step> |
@@ -1,8 +1,16 @@ | |||
.onboarding { | |||
min-height: calc(70vh - 60px); | |||
} | |||
.onboarding-step { | |||
position: relative; | |||
padding-left: 34px; | |||
} | |||
.onboarding-step:not(.is-open):not(.is-finished) { | |||
opacity: 0.4; | |||
} | |||
.onboarding-step .boxed-group-actions { | |||
height: 24px; | |||
line-height: 24px; | |||
@@ -16,16 +24,21 @@ | |||
height: 24px; | |||
line-height: 24px; | |||
border-radius: 24px; | |||
background-color: #cdcdcd; | |||
background-color: #b9b9b9; | |||
color: #fff; | |||
font-size: 14px; | |||
text-align: center; | |||
} | |||
.onboarding-step-open .onboarding-step-number { | |||
.onboarding-step.is-open .onboarding-step-number { | |||
background-color: #236a97; | |||
} | |||
.onboarding-step.is-finished { | |||
cursor: pointer; | |||
outline: none; | |||
} | |||
.onboarding-command { | |||
position: relative; | |||
margin: 8px 0; |
@@ -49,21 +49,11 @@ | |||
} | |||
.modal-large { | |||
width: 90vw; | |||
margin-left: -45vw; | |||
} | |||
.modal-full-screen { | |||
top: 30%; | |||
width: 90vw; | |||
height: 90vh; | |||
margin-left: -45vw; | |||
margin-top: -45vh; | |||
border-radius: 2px; | |||
&.ReactModal__Content--after-open { | |||
top: 50%; | |||
} | |||
width: ~"calc(100% - 40px)"; | |||
max-width: 1280px; | |||
min-width: 1040px; | |||
margin-left: 0; | |||
transform: translateX(-50%); | |||
} | |||
.modal-overlay, |
@@ -1091,9 +1091,10 @@ shortcuts.section.rules.deactivate=deactivate selected rule | |||
shortcuts.section.code=Code Page | |||
shortcuts.section.code.search=search components in the project scope | |||
tutorials.onboarding=Onboarding Tutorial | |||
tutorials.onboarding=Analyze a new project | |||
tutorials.skip=Skip this tutorial | |||
tutorials.finish=Finish this tutorial | |||
tutorials.follow_later=Follow the tutorial later in the Help section | |||
#------------------------------------------------------------------------------ | |||
@@ -2957,7 +2958,7 @@ footer.web_api=Web API | |||
#------------------------------------------------------------------------------ | |||
onboarding.header=Welcome to SonarQube! | |||
onboarding.header.sonarcloud=Welcome to SonarCloud! | |||
onboarding.header.description=Let's learn how to analyze your first public project. | |||
onboarding.header.description=Let's analyze a new project. | |||
onboarding.token.header=Generate a token | |||
onboarding.token.text=We'll use it as a replacement of the user login. This will increase the security of your installation by not letting your analysis user's password going through your network. |