diff options
Diffstat (limited to 'server/sonar-web/src')
4 files changed, 77 insertions, 50 deletions
diff --git a/server/sonar-web/src/main/js/app/components/StartupModal.tsx b/server/sonar-web/src/main/js/app/components/StartupModal.tsx index b2429cccd19..600d8ad5cb8 100644 --- a/server/sonar-web/src/main/js/app/components/StartupModal.tsx +++ b/server/sonar-web/src/main/js/app/components/StartupModal.tsx @@ -53,6 +53,7 @@ enum ModalKey { } interface State { + automatic: boolean; modal?: ModalKey; } @@ -60,17 +61,13 @@ const LICENSE_PROMPT = 'sonarqube.license.prompt'; export class StartupModal extends React.PureComponent<Props, State> { static childContextTypes = { - closeOnboardingTutorial: PropTypes.func, openOnboardingTutorial: PropTypes.func }; - state: State = {}; + state: State = { automatic: false }; getChildContext() { - return { - closeOnboardingTutorial: this.closeOnboarding, - openOnboardingTutorial: this.openOnboarding - }; + return { openOnboardingTutorial: this.openOnboarding }; } componentDidMount() { @@ -81,7 +78,7 @@ export class StartupModal extends React.PureComponent<Props, State> { this.setState(state => { if (state.modal === ModalKey.onboarding) { this.props.skipOnboarding(); - return { modal: undefined }; + return { automatic: false, modal: undefined }; } return undefined; }); @@ -90,7 +87,7 @@ export class StartupModal extends React.PureComponent<Props, State> { closeLicense = () => { this.setState(state => { if (state.modal === ModalKey.license) { - return { modal: undefined }; + return { automatic: false, modal: undefined }; } return undefined; }); @@ -112,7 +109,7 @@ export class StartupModal extends React.PureComponent<Props, State> { return showLicense().then(license => { if (!license || !license.isValidEdition) { save(LICENSE_PROMPT, toShortNotSoISOString(new Date()), currentUser.login); - this.setState({ modal: ModalKey.license }); + this.setState({ automatic: true, modal: ModalKey.license }); return Promise.resolve(); } return Promise.reject('License exists'); @@ -124,17 +121,20 @@ export class StartupModal extends React.PureComponent<Props, State> { tryAutoOpenOnboarding = () => { if (this.props.currentUser.showOnboardingTutorial) { + this.setState({ automatic: true }); this.openOnboarding(); } }; render() { - const { modal } = this.state; + const { automatic, modal } = this.state; return ( <> {this.props.children} {modal === ModalKey.license && <LicensePromptModal onClose={this.closeLicense} />} - {modal === ModalKey.onboarding && <OnboardingModal onFinish={this.closeOnboarding} />} + {modal === ModalKey.onboarding && ( + <OnboardingModal automatic={automatic} onFinish={this.closeOnboarding} /> + )} </> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js index cc04c85868c..afcf049e397 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js @@ -25,16 +25,18 @@ import TokenStep from './TokenStep'; import OrganizationStep from './OrganizationStep'; import AnalysisStep from './AnalysisStep'; import ProjectWatcher from './ProjectWatcher'; +import DeferredSpinner from '../../../components/common/DeferredSpinner'; import InstanceMessage from '../../../components/common/InstanceMessage'; import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; import { skipOnboarding } from '../../../api/users'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { getProjectUrl } from '../../../helpers/urls'; -import './styles.css'; import { isSonarCloud } from '../../../helpers/system'; +import './styles.css'; /*:: type Props = {| + automatic?:boolean, className?: string, currentUser: { login: string, isLoggedIn: boolean }, onFinish: () => void, @@ -145,7 +147,7 @@ export default class Onboarding extends React.PureComponent { return null; } - const { organizationsEnabled } = this.props; + const { automatic, organizationsEnabled } = this.props; const { step, token } = this.state; let stepNumber = 1; @@ -161,13 +163,12 @@ export default class Onboarding extends React.PureComponent { <InstanceMessage message={translate('onboarding.header')} /> </h1> <div className="page-actions"> - {this.state.skipping ? ( - <i className="spinner" /> - ) : ( + <DeferredSpinner loading={this.state.skipping}> <a className="js-skip text-muted" href="#" onClick={this.handleSkipClick}> - {translate('tutorials.skip')} + {automatic ? translate('tutorials.skip') : translate('close')} </a> - )} + </DeferredSpinner> + <p className="note"> {translate( isSonarCloud() diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx index e1013a3f750..188e5cc7927 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx @@ -23,15 +23,16 @@ import { translate } from '../../../helpers/l10n'; import { lazyLoad } from '../../../components/lazyLoad'; interface Props { + automatic?: boolean; onFinish: () => void; } const OnboardingContainer = lazyLoad(() => import('./OnboardingContainer')); -export default function OnboardingModal({ onFinish }: Props) { +export default function OnboardingModal(props: Props) { return ( <Modal contentLabel={translate('tutorials.onboarding')} large={true}> - <OnboardingContainer onFinish={onFinish} /> + <OnboardingContainer {...props} /> </Modal> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap index 313284fb6a0..1635dc70bd5 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap @@ -23,13 +23,18 @@ exports[`guides for on-premise 1`] = ` <div className="page-actions" > - <a - className="js-skip text-muted" - href="#" - onClick={[Function]} + <DeferredSpinner + loading={false} + timeout={100} > - tutorials.skip - </a> + <a + className="js-skip text-muted" + href="#" + onClick={[Function]} + > + close + </a> + </DeferredSpinner> <p className="note" > @@ -88,13 +93,18 @@ exports[`guides for on-premise 2`] = ` <div className="page-actions" > - <a - className="js-skip text-muted" - href="#" - onClick={[Function]} + <DeferredSpinner + loading={false} + timeout={100} > - tutorials.skip - </a> + <a + className="js-skip text-muted" + href="#" + onClick={[Function]} + > + close + </a> + </DeferredSpinner> <p className="note" > @@ -152,13 +162,18 @@ exports[`guides for sonarcloud 1`] = ` <div className="page-actions" > - <a - className="js-skip text-muted" - href="#" - onClick={[Function]} + <DeferredSpinner + loading={false} + timeout={100} > - tutorials.skip - </a> + <a + className="js-skip text-muted" + href="#" + onClick={[Function]} + > + close + </a> + </DeferredSpinner> <p className="note" > @@ -228,13 +243,18 @@ exports[`guides for sonarcloud 2`] = ` <div className="page-actions" > - <a - className="js-skip text-muted" - href="#" - onClick={[Function]} + <DeferredSpinner + loading={false} + timeout={100} > - tutorials.skip - </a> + <a + className="js-skip text-muted" + href="#" + onClick={[Function]} + > + close + </a> + </DeferredSpinner> <p className="note" > @@ -305,13 +325,18 @@ exports[`guides for sonarcloud 3`] = ` <div className="page-actions" > - <a - className="js-skip text-muted" - href="#" - onClick={[Function]} + <DeferredSpinner + loading={false} + timeout={100} > - tutorials.skip - </a> + <a + className="js-skip text-muted" + href="#" + onClick={[Function]} + > + close + </a> + </DeferredSpinner> <p className="note" > |