aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-06-15 15:04:21 +0200
committerSonarTech <sonartech@sonarsource.com>2018-06-21 20:21:29 +0200
commit4e91bd432aeef4a2e7ff680910907e62007ac801 (patch)
treec1e8ff11fefd379dcd57ae152c766e99e6ec3e98 /server/sonar-web/src/main/js/apps
parent7a8b69cb8e9e6cd0d47b5dc3f5dc4ab9e2368661 (diff)
downloadsonarqube-4e91bd432aeef4a2e7ff680910907e62007ac801.tar.gz
sonarqube-4e91bd432aeef4a2e7ff680910907e62007ac801.zip
SONARCLOUD-64 New onboarding with 3 cases for SonarCloud (#383)
* SONARCLOUD-64 Move Onboarding to ProjectOnboarding * SONARCLOUD-64 Migrate project onboarding to TS * SONARCLOUD-64 Update ProjectOnboarding style * SONARCLOUD-64 Add main onboarding page
Diffstat (limited to 'server/sonar-web/src/main/js/apps')
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/Onboarding.tsx102
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/__tests__/Onboarding-test.tsx61
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/__tests__/__snapshots__/Onboarding-test.tsx.snap82
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js236
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js33
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap388
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/AnalysisStep.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js)149
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/LanguageStep.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js)51
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/NewOrganizationForm.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js)45
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/NewProjectForm.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js)49
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/OrganizationStep.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js)58
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboarding.tsx206
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboardingModal.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx)6
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboardingPage.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingPage.tsx)8
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectWatcher.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js)58
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/Step.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js)30
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/TokenStep.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js)102
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/LanguageStep-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/LanguageStep-test.js)47
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/NewOrganizationForm-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/NewOrganizationForm-test.js)5
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/NewProjectForm-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/NewProjectForm-test.js)5
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/OrganizationStep-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js)11
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/ProjectOnboarding-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js)35
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/ProjectWatcher-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/ProjectWatcher-test.js)3
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/Step-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Step-test.js)3
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/TokenStep-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/TokenStep-test.js)5
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/LanguageStep-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/LanguageStep-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/NewOrganizationForm-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/NewOrganizationForm-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/NewProjectForm-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/NewProjectForm-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/OrganizationStep-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectOnboarding-test.tsx.snap349
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectWatcher-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/ProjectWatcher-test.js.snap)8
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/Step-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Step-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/TokenStep-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/TokenStep-test.js.snap)12
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/BuildWrapper.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js)20
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/ClangGCC.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js)23
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/DotNet.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js)19
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/JavaGradle.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js)17
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/JavaMaven.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js)17
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/MSBuildScanner.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js)15
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/Msvc.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js)19
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/Other.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js)21
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/SQScanner.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js)17
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/BuildWrapper-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/BuildWrapper-test.js)3
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/ClangGCC-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/ClangGCC-test.js)6
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/DotNet-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/DotNet-test.js)4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/JavaGradle-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/JavaGradle-test.js)4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/JavaMaven-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/JavaMaven-test.js)4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/MSBuildScanner-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/MSBuildScanner-test.js)4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/Msvc-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/Msvc-test.js)4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/Other-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/Other-test.js)6
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/SQScanner-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/SQScanner-test.js)4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/BuildWrapper-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/ClangGCC-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/DotNet-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/DotNet-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/JavaGradle-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/JavaMaven-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/MSBuildScanner-test.js.snap)1
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/Msvc-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Msvc-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/Other-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Other-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/SQScanner-test.js.snap)3
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/styles.css (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/styles.css)15
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx68
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/TeamOnboardingModal-test.tsx (renamed from server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.d.ts)10
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap61
65 files changed, 1357 insertions, 1159 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.tsx b/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.tsx
index 6c52d002bb1..4cd7b7d2164 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.tsx
+++ b/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.tsx
@@ -36,13 +36,13 @@ interface StateProps {
export class NoFavoriteProjects extends React.PureComponent<StateProps> {
static contextTypes = {
- openOnboardingTutorial: PropTypes.func
+ openProjectOnboarding: PropTypes.func
};
onAnalyzeProjectClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
event.preventDefault();
event.currentTarget.blur();
- this.context.openOnboardingTutorial();
+ this.context.openProjectOnboarding();
};
render() {
diff --git a/server/sonar-web/src/main/js/apps/tutorials/Onboarding.tsx b/server/sonar-web/src/main/js/apps/tutorials/Onboarding.tsx
new file mode 100644
index 00000000000..e6a6d887bd3
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/Onboarding.tsx
@@ -0,0 +1,102 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { connect } from 'react-redux';
+import handleRequiredAuthentication from '../../app/utils/handleRequiredAuthentication';
+import Modal from '../../components/controls/Modal';
+import { ResetButtonLink, Button } from '../../components/ui/buttons';
+import { translate } from '../../helpers/l10n';
+import { CurrentUser, isLoggedIn } from '../../app/types';
+import { getCurrentUser } from '../../store/rootReducer';
+import './styles.css';
+
+interface OwnProps {
+ onFinish: () => void;
+ onOpenOrganizationOnboarding: () => void;
+ onOpenProjectOnboarding: () => void;
+ onOpenTeamOnboarding: () => void;
+}
+
+interface StateProps {
+ currentUser: CurrentUser;
+}
+
+type Props = OwnProps & StateProps;
+
+export class Onboarding extends React.PureComponent<Props> {
+ componentDidMount() {
+ if (!isLoggedIn(this.props.currentUser)) {
+ handleRequiredAuthentication();
+ }
+ }
+
+ render() {
+ if (!isLoggedIn(this.props.currentUser)) {
+ return null;
+ }
+
+ const header = translate('onboarding.header');
+ return (
+ <Modal
+ contentLabel={header}
+ medium={true}
+ onRequestClose={this.props.onFinish}
+ shouldCloseOnOverlayClick={false}>
+ <header className="modal-head">
+ <h2>{header}</h2>
+ </header>
+ <div className="modal-body">
+ <p className="spacer-top big-spacer-bottom">
+ {translate('onboarding.header.description')}
+ </p>
+ <ul className="onboarding-choices">
+ <li className="text-center">
+ <p className="big-spacer-bottom">{translate('onboarding.analyze_public_code')}</p>
+ <Button onClick={this.props.onOpenProjectOnboarding}>
+ {translate('onboarding.analyze_public_code.button')}
+ </Button>
+ </li>
+ <li className="text-center">
+ <p className="big-spacer-bottom">{translate('onboarding.analyze_private_code')}</p>
+ <Button onClick={this.props.onOpenOrganizationOnboarding}>
+ {translate('onboarding.analyze_private_code.button')}
+ </Button>
+ </li>
+ <li className="text-center">
+ <p className="big-spacer-bottom">
+ {translate('onboarding.contribute_existing_project')}
+ </p>
+ <Button onClick={this.props.onOpenTeamOnboarding}>
+ {translate('onboarding.contribute_existing_project.button')}
+ </Button>
+ </li>
+ </ul>
+ </div>
+ <footer className="modal-foot">
+ <ResetButtonLink onClick={this.props.onFinish}>{translate('close')}</ResetButtonLink>
+ </footer>
+ </Modal>
+ );
+ }
+}
+
+const mapStateToProps = (state: any): StateProps => ({ currentUser: getCurrentUser(state) });
+
+export default connect<StateProps, {}, OwnProps>(mapStateToProps)(Onboarding);
diff --git a/server/sonar-web/src/main/js/apps/tutorials/__tests__/Onboarding-test.tsx b/server/sonar-web/src/main/js/apps/tutorials/__tests__/Onboarding-test.tsx
new file mode 100644
index 00000000000..c9b3e77500e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/__tests__/Onboarding-test.tsx
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import { Onboarding } from '../Onboarding';
+import { click } from '../../../helpers/testUtils';
+
+it('renders correctly', () => {
+ expect(
+ shallow(
+ <Onboarding
+ currentUser={{ isLoggedIn: true }}
+ onFinish={jest.fn()}
+ onOpenOrganizationOnboarding={jest.fn()}
+ onOpenProjectOnboarding={jest.fn()}
+ onOpenTeamOnboarding={jest.fn()}
+ />
+ )
+ ).toMatchSnapshot();
+});
+
+it('should correctly open the different tutorials', () => {
+ const onFinish = jest.fn();
+ const onOpenOrganizationOnboarding = jest.fn();
+ const onOpenProjectOnboarding = jest.fn();
+ const onOpenTeamOnboarding = jest.fn();
+ const wrapper = shallow(
+ <Onboarding
+ currentUser={{ isLoggedIn: true }}
+ onFinish={onFinish}
+ onOpenOrganizationOnboarding={onOpenOrganizationOnboarding}
+ onOpenProjectOnboarding={onOpenProjectOnboarding}
+ onOpenTeamOnboarding={onOpenTeamOnboarding}
+ />
+ );
+
+ click(wrapper.find('ResetButtonLink'));
+ expect(onFinish).toHaveBeenCalled();
+
+ wrapper.find('Button').forEach(button => click(button));
+ expect(onOpenOrganizationOnboarding).toHaveBeenCalled();
+ expect(onOpenProjectOnboarding).toHaveBeenCalled();
+ expect(onOpenTeamOnboarding).toHaveBeenCalled();
+});
diff --git a/server/sonar-web/src/main/js/apps/tutorials/__tests__/__snapshots__/Onboarding-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/__tests__/__snapshots__/Onboarding-test.tsx.snap
new file mode 100644
index 00000000000..e017f778601
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/__tests__/__snapshots__/Onboarding-test.tsx.snap
@@ -0,0 +1,82 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders correctly 1`] = `
+<Modal
+ contentLabel="onboarding.header"
+ medium={true}
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+>
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.header
+ </h2>
+ </header>
+ <div
+ className="modal-body"
+ >
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.header.description
+ </p>
+ <ul
+ className="onboarding-choices"
+ >
+ <li
+ className="text-center"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ onboarding.analyze_public_code
+ </p>
+ <Button
+ onClick={[MockFunction]}
+ >
+ onboarding.analyze_public_code.button
+ </Button>
+ </li>
+ <li
+ className="text-center"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ onboarding.analyze_private_code
+ </p>
+ <Button
+ onClick={[MockFunction]}
+ >
+ onboarding.analyze_private_code.button
+ </Button>
+ </li>
+ <li
+ className="text-center"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ onboarding.contribute_existing_project
+ </p>
+ <Button
+ onClick={[MockFunction]}
+ >
+ onboarding.contribute_existing_project.button
+ </Button>
+ </li>
+ </ul>
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ close
+ </ResetButtonLink>
+ </footer>
+</Modal>
+`;
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
deleted file mode 100644
index afcf049e397..00000000000
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import PropTypes from 'prop-types';
-import Helmet from 'react-helmet';
-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 { isSonarCloud } from '../../../helpers/system';
-import './styles.css';
-
-/*::
-type Props = {|
- automatic?:boolean,
- className?: string,
- currentUser: { login: string, isLoggedIn: boolean },
- onFinish: () => void,
- organizationsEnabled: boolean
-|};
-*/
-
-/*::
-type State = {
- finished: boolean,
- organization?: string,
- projectKey?: string,
- skipping: boolean,
- step: string,
- token?: string
-};
-*/
-
-export default class Onboarding extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- /*:: state: State; */
-
- static contextTypes = {
- router: PropTypes.object
- };
-
- constructor(props /*: Props */) {
- super(props);
- this.state = {
- finished: false,
- skipping: false,
- step: props.organizationsEnabled ? 'organization' : 'token'
- };
- }
-
- componentDidMount() {
- this.mounted = true;
-
- // useCapture = true to receive the event before inputs
- window.addEventListener('keydown', this.onKeyDown, true);
-
- if (!this.props.currentUser.isLoggedIn) {
- handleRequiredAuthentication();
- }
- }
-
- componentWillUnmount() {
- window.removeEventListener('keydown', this.onKeyDown, true);
- this.mounted = false;
- }
-
- onKeyDown = (event /*: KeyboardEvent */) => {
- // ESC key
- if (event.keyCode === 27) {
- this.finishOnboarding();
- }
- };
-
- finishOnboarding = () => {
- this.setState({ skipping: true });
- skipOnboarding().then(
- () => {
- if (this.mounted) {
- this.props.onFinish();
-
- if (this.state.projectKey) {
- this.context.router.push(getProjectUrl(this.state.projectKey));
- }
- }
- },
- () => {
- if (this.mounted) {
- this.setState({ skipping: false });
- }
- }
- );
- };
-
- handleTimeout = () => {
- // unset `projectKey` to display a generic "Finish this tutorial" button
- this.setState({ projectKey: undefined });
- };
-
- handleTokenDone = (token /*: string */) => {
- this.setState({ step: 'analysis', token });
- };
-
- handleOrganizationDone = (organization /*: string */) => {
- this.setState({ organization, step: 'token' });
- };
-
- handleTokenOpen = () => this.setState({ step: 'token' });
-
- handleOrganizationOpen = () => this.setState({ step: 'organization' });
-
- handleSkipClick = (event /*: Event */) => {
- event.preventDefault();
- this.finishOnboarding();
- };
-
- handleFinish = (projectKey /*: string | void */) => this.setState({ finished: true, projectKey });
-
- handleReset = () => this.setState({ finished: false, projectKey: undefined });
-
- render() {
- if (!this.props.currentUser.isLoggedIn) {
- return null;
- }
-
- const { automatic, organizationsEnabled } = this.props;
- const { step, token } = this.state;
- let stepNumber = 1;
-
- return (
- <div className={this.props.className}>
- <InstanceMessage message={translate('onboarding.header')}>
- {transformedMessage => <Helmet title={transformedMessage} titleTemplate="%s" />}
- </InstanceMessage>
-
- <div className="page page-limited onboarding">
- <header className="page-header">
- <h1 className="page-title">
- <InstanceMessage message={translate('onboarding.header')} />
- </h1>
- <div className="page-actions">
- <DeferredSpinner loading={this.state.skipping}>
- <a className="js-skip text-muted" href="#" onClick={this.handleSkipClick}>
- {automatic ? translate('tutorials.skip') : translate('close')}
- </a>
- </DeferredSpinner>
-
- <p className="note">
- {translate(
- isSonarCloud()
- ? 'tutorials.find_it_back_in_plus'
- : 'tutorials.find_it_back_in_help'
- )}
- </p>
- </div>
- <div className="page-description">
- {translateWithParameters(
- 'onboarding.header.description',
- organizationsEnabled ? 3 : 2
- )}
- </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
- currentUser={this.props.currentUser}
- finished={this.state.token != null}
- onContinue={this.handleTokenDone}
- onOpen={this.handleTokenOpen}
- open={step === 'token'}
- stepNumber={stepNumber++}
- />
-
- <AnalysisStep
- onFinish={this.handleFinish}
- onReset={this.handleReset}
- open={step === 'analysis'}
- organization={this.state.organization}
- 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>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js
deleted file mode 100644
index cf27d5dd333..00000000000
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-// @flow
-import { connect } from 'react-redux';
-import Onboarding from './Onboarding';
-import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- className: 'modal-container',
- currentUser: getCurrentUser(state),
- organizationsEnabled: areThereCustomOrganizations(state)
- };
-};
-
-export default connect(mapStateToProps)(Onboarding);
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
deleted file mode 100644
index 1635dc70bd5..00000000000
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap
+++ /dev/null
@@ -1,388 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`guides for on-premise 1`] = `
-<div
- className="modal-container"
->
- <InstanceMessage
- message="onboarding.header"
- />
- <div
- className="page page-limited onboarding"
- >
- <header
- className="page-header"
- >
- <h1
- className="page-title"
- >
- <InstanceMessage
- message="onboarding.header"
- />
- </h1>
- <div
- className="page-actions"
- >
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <a
- className="js-skip text-muted"
- href="#"
- onClick={[Function]}
- >
- close
- </a>
- </DeferredSpinner>
- <p
- className="note"
- >
- tutorials.find_it_back_in_help
- </p>
- </div>
- <div
- className="page-description"
- >
- onboarding.header.description.2
- </div>
- </header>
- <TokenStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={false}
- onContinue={[Function]}
- onOpen={[Function]}
- open={true}
- stepNumber={1}
- />
- <AnalysisStep
- onFinish={[Function]}
- onReset={[Function]}
- open={false}
- stepNumber={2}
- />
- </div>
-</div>
-`;
-
-exports[`guides for on-premise 2`] = `
-<div
- className="modal-container"
->
- <InstanceMessage
- message="onboarding.header"
- />
- <div
- className="page page-limited onboarding"
- >
- <header
- className="page-header"
- >
- <h1
- className="page-title"
- >
- <InstanceMessage
- message="onboarding.header"
- />
- </h1>
- <div
- className="page-actions"
- >
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <a
- className="js-skip text-muted"
- href="#"
- onClick={[Function]}
- >
- close
- </a>
- </DeferredSpinner>
- <p
- className="note"
- >
- tutorials.find_it_back_in_help
- </p>
- </div>
- <div
- className="page-description"
- >
- onboarding.header.description.2
- </div>
- </header>
- <TokenStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={true}
- onContinue={[Function]}
- onOpen={[Function]}
- open={false}
- stepNumber={1}
- />
- <AnalysisStep
- onFinish={[Function]}
- onReset={[Function]}
- open={true}
- stepNumber={2}
- token="abcd1234"
- />
- </div>
-</div>
-`;
-
-exports[`guides for sonarcloud 1`] = `
-<div>
- <InstanceMessage
- message="onboarding.header"
- />
- <div
- className="page page-limited onboarding"
- >
- <header
- className="page-header"
- >
- <h1
- className="page-title"
- >
- <InstanceMessage
- message="onboarding.header"
- />
- </h1>
- <div
- className="page-actions"
- >
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <a
- className="js-skip text-muted"
- href="#"
- onClick={[Function]}
- >
- close
- </a>
- </DeferredSpinner>
- <p
- className="note"
- >
- tutorials.find_it_back_in_plus
- </p>
- </div>
- <div
- className="page-description"
- >
- onboarding.header.description.3
- </div>
- </header>
- <OrganizationStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={false}
- onContinue={[Function]}
- onOpen={[Function]}
- open={true}
- stepNumber={1}
- />
- <TokenStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={false}
- onContinue={[Function]}
- onOpen={[Function]}
- open={false}
- stepNumber={2}
- />
- <AnalysisStep
- onFinish={[Function]}
- onReset={[Function]}
- open={false}
- stepNumber={3}
- />
- </div>
-</div>
-`;
-
-exports[`guides for sonarcloud 2`] = `
-<div>
- <InstanceMessage
- message="onboarding.header"
- />
- <div
- className="page page-limited onboarding"
- >
- <header
- className="page-header"
- >
- <h1
- className="page-title"
- >
- <InstanceMessage
- message="onboarding.header"
- />
- </h1>
- <div
- className="page-actions"
- >
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <a
- className="js-skip text-muted"
- href="#"
- onClick={[Function]}
- >
- close
- </a>
- </DeferredSpinner>
- <p
- className="note"
- >
- tutorials.find_it_back_in_plus
- </p>
- </div>
- <div
- className="page-description"
- >
- onboarding.header.description.3
- </div>
- </header>
- <OrganizationStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={true}
- onContinue={[Function]}
- onOpen={[Function]}
- open={false}
- stepNumber={1}
- />
- <TokenStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={false}
- onContinue={[Function]}
- onOpen={[Function]}
- open={true}
- stepNumber={2}
- />
- <AnalysisStep
- onFinish={[Function]}
- onReset={[Function]}
- open={false}
- organization="my-org"
- stepNumber={3}
- />
- </div>
-</div>
-`;
-
-exports[`guides for sonarcloud 3`] = `
-<div>
- <InstanceMessage
- message="onboarding.header"
- />
- <div
- className="page page-limited onboarding"
- >
- <header
- className="page-header"
- >
- <h1
- className="page-title"
- >
- <InstanceMessage
- message="onboarding.header"
- />
- </h1>
- <div
- className="page-actions"
- >
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <a
- className="js-skip text-muted"
- href="#"
- onClick={[Function]}
- >
- close
- </a>
- </DeferredSpinner>
- <p
- className="note"
- >
- tutorials.find_it_back_in_plus
- </p>
- </div>
- <div
- className="page-description"
- >
- onboarding.header.description.3
- </div>
- </header>
- <OrganizationStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={true}
- onContinue={[Function]}
- onOpen={[Function]}
- open={false}
- stepNumber={1}
- />
- <TokenStep
- currentUser={
- Object {
- "isLoggedIn": true,
- "login": "admin",
- }
- }
- finished={true}
- onContinue={[Function]}
- onOpen={[Function]}
- open={false}
- stepNumber={2}
- />
- <AnalysisStep
- onFinish={[Function]}
- onReset={[Function]}
- open={true}
- organization="my-org"
- stepNumber={3}
- token="abcd1234"
- />
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/AnalysisStep.tsx
index afaa359bfb7..a91ff541119 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/AnalysisStep.tsx
@@ -17,11 +17,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import Step from './Step';
-import LanguageStep from './LanguageStep';
-/*:: import type { Result } from './LanguageStep'; */
+import LanguageStep, { Result } from './LanguageStep';
import JavaMaven from './commands/JavaMaven';
import JavaGradle from './commands/JavaGradle';
import DotNet from './commands/DotNet';
@@ -31,28 +29,23 @@ import Other from './commands/Other';
import { translate } from '../../../helpers/l10n';
import { getHostUrl } from '../../../helpers/urls';
-/*::
-type Props = {|
- onFinish: (projectKey?: string) => void,
- onReset: () => void,
- open: boolean,
- organization?: string,
- stepNumber: number,
- token: string
-|};
-*/
-
-/*::
-type State = {
- result?: Result
-};
-*/
-
-export default class AnalysisStep extends React.PureComponent {
- /*:: props: Props; */
- state /*: State */ = {};
-
- handleLanguageSelect = (result /*: Result | void */) => {
+interface Props {
+ onFinish: (projectKey?: string) => void;
+ onReset: () => void;
+ open: boolean;
+ organization?: string;
+ stepNumber: number;
+ token?: string;
+}
+
+interface State {
+ result?: Result;
+}
+
+export default class AnalysisStep extends React.PureComponent<Props, State> {
+ state: State = {};
+
+ handleLanguageSelect = (result?: Result) => {
this.setState({ result });
const projectKey = result && result.language !== 'java' ? result.projectKey : undefined;
this.props.onFinish(projectKey);
@@ -80,7 +73,7 @@ export default class AnalysisStep extends React.PureComponent {
);
};
- renderFormattedCommand = (...lines /*: Array<string> */) => (
+ renderFormattedCommand = (...lines: Array<string>) => (
// keep this "useless" concatentation for the readability reason
// eslint-disable-next-line no-useless-concat
<pre>{lines.join(' ' + '\\' + '\n' + ' ')}</pre>
@@ -108,69 +101,87 @@ export default class AnalysisStep extends React.PureComponent {
}
};
- renderCommandForMaven = () => (
- <JavaMaven
- host={getHostUrl()}
- organization={this.props.organization}
- token={this.props.token}
- />
- );
+ renderCommandForMaven = () => {
+ const { token } = this.props;
+ if (!token) {
+ return null;
+ }
+ return <JavaMaven host={getHostUrl()} organization={this.props.organization} token={token} />;
+ };
- renderCommandForGradle = () => (
- <JavaGradle
- host={getHostUrl()}
- organization={this.props.organization}
- token={this.props.token}
- />
- );
+ renderCommandForGradle = () => {
+ const { token } = this.props;
+ if (!token) {
+ return null;
+ }
+ return <JavaGradle host={getHostUrl()} organization={this.props.organization} token={token} />;
+ };
renderCommandForDotNet = () => {
+ const { token } = this.props;
+ const { result } = this.state;
+ if (!result || !result.projectKey || !token) {
+ return null;
+ }
return (
<DotNet
host={getHostUrl()}
organization={this.props.organization}
- // $FlowFixMe
- projectKey={this.state.result.projectKey}
- token={this.props.token}
+ projectKey={result.projectKey}
+ token={token}
/>
);
};
renderCommandForMSVC = () => {
+ const { token } = this.props;
+ const { result } = this.state;
+ if (!result || !result.projectKey || !token) {
+ return null;
+ }
return (
<Msvc
host={getHostUrl()}
organization={this.props.organization}
- // $FlowFixMe
- projectKey={this.state.result.projectKey}
- token={this.props.token}
+ projectKey={result.projectKey}
+ token={token}
/>
);
};
- renderCommandForClangGCC = () => (
- <ClangGCC
- host={getHostUrl()}
- organization={this.props.organization}
- // $FlowFixMe
- os={this.state.result.os}
- // $FlowFixMe
- projectKey={this.state.result.projectKey}
- token={this.props.token}
- />
- );
+ renderCommandForClangGCC = () => {
+ const { token } = this.props;
+ const { result } = this.state;
+ if (!result || !result.projectKey || !result.os || !token) {
+ return null;
+ }
+ return (
+ <ClangGCC
+ host={getHostUrl()}
+ organization={this.props.organization}
+ os={result.os}
+ projectKey={result.projectKey}
+ token={token}
+ />
+ );
+ };
- renderCommandForOther = () => (
- <Other
- host={getHostUrl()}
- organization={this.props.organization}
- // $FlowFixMe
- os={this.state.result.os}
- // $FlowFixMe
- projectKey={this.state.result.projectKey}
- token={this.props.token}
- />
- );
+ renderCommandForOther = () => {
+ const { token } = this.props;
+ const { result } = this.state;
+ if (!result || !result.projectKey || !result.os || !token) {
+ return null;
+ }
+ return (
+ <Other
+ host={getHostUrl()}
+ organization={this.props.organization}
+ os={result.os}
+ projectKey={result.projectKey}
+ token={token}
+ />
+ );
+ };
renderResult = () => null;
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/LanguageStep.tsx
index c9bd1c15e5a..25b7544ddcc 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/LanguageStep.tsx
@@ -17,38 +17,31 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import NewProjectForm from './NewProjectForm';
import RadioToggle from '../../../components/controls/RadioToggle';
import { translate } from '../../../helpers/l10n';
import { isSonarCloud } from '../../../helpers/system';
-/*::
-type Props = {|
- onDone: (result: Result) => void,
- onReset: () => void,
- organization?: string,
-|};
-*/
-
-/*::
-type State = {
- language?: string,
- javaBuild?: string,
- cFamilyCompiler?: string,
- os?: string,
- projectKey?: string
-};
-*/
+export interface Result {
+ language?: string;
+ javaBuild?: string;
+ cFamilyCompiler?: string;
+ os?: string;
+ projectKey?: string;
+}
-/*::
-export type Result = State; */
+interface Props {
+ onDone: (result: Result) => void;
+ onReset: () => void;
+ organization?: string;
+}
-export default class LanguageStep extends React.PureComponent {
- /*:: props: Props; */
+type State = Result;
- state /*: State */ = {};
+export default class LanguageStep extends React.PureComponent<Props, State> {
+ state: State = {};
isConfigured = () => {
const { language, javaBuild, cFamilyCompiler, os, projectKey } = this.state;
@@ -69,23 +62,23 @@ export default class LanguageStep extends React.PureComponent {
}
};
- handleLanguageChange = (language /*: string */) => {
+ handleLanguageChange = (language: string) => {
this.setState({ language }, this.handleChange);
};
- handleJavaBuildChange = (javaBuild /*: string */) => {
+ handleJavaBuildChange = (javaBuild: string) => {
this.setState({ javaBuild }, this.handleChange);
};
- handleCFamilyCompilerChange = (cFamilyCompiler /*: string */) => {
+ handleCFamilyCompilerChange = (cFamilyCompiler: string) => {
this.setState({ cFamilyCompiler }, this.handleChange);
};
- handleOSChange = (os /*: string */) => {
+ handleOSChange = (os: string) => {
this.setState({ os }, this.handleChange);
};
- handleProjectKeyDone = (projectKey /*: string */) => {
+ handleProjectKeyDone = (projectKey: string) => {
this.setState({ projectKey }, this.handleChange);
};
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/NewOrganizationForm.tsx
index 11be750a41b..1a0e5500129 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/NewOrganizationForm.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { debounce } from 'lodash';
import {
createOrganization,
@@ -29,29 +28,23 @@ import AlertErrorIcon from '../../../components/icons-components/AlertErrorIcon'
import { DeleteButton, SubmitButton } from '../../../components/ui/buttons';
import { translate } from '../../../helpers/l10n';
-/*::
-type Props = {|
- onDelete: () => void,
- onDone: (organization: string) => void,
- organization?: string
-|};
-*/
+interface Props {
+ onDelete: () => void;
+ onDone: (organization: string) => void;
+ organization?: string;
+}
-/*::
-type State = {
- done: boolean,
- loading: boolean,
- organization: string,
- unique: boolean
-};
-*/
+interface State {
+ done: boolean;
+ loading: boolean;
+ organization: string;
+ unique: boolean;
+}
-export default class NewOrganizationForm extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- /*:: state: State; */
+export default class NewOrganizationForm extends React.PureComponent<Props, State> {
+ mounted = false;
- constructor(props /*: Props */) {
+ constructor(props: Props) {
super(props);
this.state = {
done: props.organization != null,
@@ -76,7 +69,7 @@ export default class NewOrganizationForm extends React.PureComponent {
}
};
- validateOrganization = (organization /*: string */) => {
+ validateOrganization = (organization: string) => {
getOrganization(organization).then(response => {
if (this.mounted) {
this.setState({ unique: response == null });
@@ -84,19 +77,19 @@ export default class NewOrganizationForm extends React.PureComponent {
});
};
- sanitizeOrganization = (organization /*: string */) =>
+ sanitizeOrganization = (organization: string) =>
organization
.toLowerCase()
.replace(/[^a-z0-9-]/, '')
.replace(/^-/, '');
- handleOrganizationChange = (event /*: { target: HTMLInputElement } */) => {
+ handleOrganizationChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const organization = this.sanitizeOrganization(event.target.value);
this.setState({ organization });
this.validateOrganization(organization);
};
- handleOrganizationCreate = (event /*: Event */) => {
+ handleOrganizationCreate = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { organization } = this.state;
if (organization) {
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/NewProjectForm.tsx
index cde4629a0a8..f09b4d152bf 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/NewProjectForm.tsx
@@ -17,35 +17,28 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { createProject, deleteProject } from '../../../api/components';
import { DeleteButton, SubmitButton } from '../../../components/ui/buttons';
import { translate } from '../../../helpers/l10n';
-/*::
-type Props = {|
- onDelete: () => void,
- onDone: (projectKey: string) => void,
- organization?: string,
- projectKey?: string
-|};
-*/
+interface Props {
+ onDelete: () => void;
+ onDone: (projectKey: string) => void;
+ organization?: string;
+ projectKey?: string;
+}
-/*::
-type State = {
- done: boolean,
- loading: boolean,
- projectKey: string
-};
-*/
+interface State {
+ done: boolean;
+ loading: boolean;
+ projectKey: string;
+}
-export default class NewProjectForm extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- /*:: state: State; */
+export default class NewProjectForm extends React.PureComponent<Props, State> {
+ mounted = false;
- constructor(props /*: Props */) {
+ constructor(props: Props) {
super(props);
this.state = {
done: props.projectKey != null,
@@ -68,16 +61,20 @@ export default class NewProjectForm extends React.PureComponent {
}
};
- sanitizeProjectKey = (projectKey /*: string */) => projectKey.replace(/[^-_a-zA-Z0-9.:]/, '');
+ sanitizeProjectKey = (projectKey: string) => projectKey.replace(/[^-_a-zA-Z0-9.:]/, '');
- handleProjectKeyChange = (event /*: { target: HTMLInputElement } */) => {
+ handleProjectKeyChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ projectKey: this.sanitizeProjectKey(event.target.value) });
};
- handleProjectCreate = (event /*: Event */) => {
+ handleProjectCreate = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { projectKey } = this.state;
- const data /*: { [string]: string } */ = {
+ const data: {
+ name: string;
+ project: string;
+ organization?: string;
+ } = {
name: projectKey,
project: projectKey
};
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/OrganizationStep.tsx
index e55c34a341a..0d155ef9eee 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/OrganizationStep.tsx
@@ -17,9 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
-import classNames from 'classnames';
+import * as React from 'react';
+import * as classNames from 'classnames';
import { sortBy } from 'lodash';
import Step from './Step';
import NewOrganizationForm from './NewOrganizationForm';
@@ -30,32 +29,27 @@ import Select from '../../../components/controls/Select';
import { translate } from '../../../helpers/l10n';
import { Button } from '../../../components/ui/buttons';
-/*::
-type Props = {|
- currentUser: { login: string, isLoggedIn: boolean },
- finished: boolean,
- onOpen: () => void,
- onContinue: (organization: string) => void,
- open: boolean,
- stepNumber: number
-|};
-*/
+interface Props {
+ currentUser: { login: string; isLoggedIn: boolean };
+ finished: boolean;
+ onOpen: () => void;
+ onContinue: (organization: string) => void;
+ open: boolean;
+ stepNumber: number;
+}
-/*::
-type State = {
- loading: boolean,
- newOrganization?: string,
- existingOrganization?: string,
- existingOrganizations: Array<string>,
- personalOrganization?: string,
- selection: 'personal' | 'existing' | 'new'
-};
-*/
+interface State {
+ loading: boolean;
+ newOrganization?: string;
+ existingOrganization?: string;
+ existingOrganizations: Array<string>;
+ personalOrganization?: string;
+ selection: 'personal' | 'existing' | 'new';
+}
-export default class OrganizationStep extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
+export default class OrganizationStep extends React.PureComponent<Props, State> {
+ mounted = false;
+ state: State = {
loading: true,
existingOrganizations: [],
selection: 'personal'
@@ -112,22 +106,22 @@ export default class OrganizationStep extends React.PureComponent {
}
};
- handlePersonalClick = (event /*: Event */) => {
+ handlePersonalClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.setState({ selection: 'personal' });
};
- handleExistingClick = (event /*: Event */) => {
+ handleExistingClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.setState({ selection: 'existing' });
};
- handleNewClick = (event /*: Event */) => {
+ handleNewClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.setState({ selection: 'new' });
};
- handleOrganizationCreate = (newOrganization /*: string */) => {
+ handleOrganizationCreate = (newOrganization: string) => {
this.setState({ newOrganization });
};
@@ -135,7 +129,7 @@ export default class OrganizationStep extends React.PureComponent {
this.setState({ newOrganization: undefined });
};
- handleExistingOrganizationSelect = ({ value } /*: { value: string } */) => {
+ handleExistingOrganizationSelect = ({ value }: { value: string }) => {
this.setState({ existingOrganization: value });
};
diff --git a/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboarding.tsx b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboarding.tsx
new file mode 100644
index 00000000000..384e1726e39
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboarding.tsx
@@ -0,0 +1,206 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import * as PropTypes from 'prop-types';
+import Helmet from 'react-helmet';
+import { connect } from 'react-redux';
+import TokenStep from './TokenStep';
+import OrganizationStep from './OrganizationStep';
+import AnalysisStep from './AnalysisStep';
+import ProjectWatcher from './ProjectWatcher';
+import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication';
+import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer';
+import { CurrentUser, isLoggedIn } from '../../../app/types';
+import { ResetButtonLink } from '../../../components/ui/buttons';
+import { getProjectUrl } from '../../../helpers/urls';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { isSonarCloud } from '../../../helpers/system';
+import '../styles.css';
+
+interface OwnProps {
+ automatic?: boolean;
+ onFinish: () => void;
+}
+
+interface StateProps {
+ currentUser: CurrentUser;
+ organizationsEnabled: boolean;
+}
+
+type Props = OwnProps & StateProps;
+
+interface State {
+ finished: boolean;
+ organization?: string;
+ projectKey?: string;
+ step: string;
+ token?: string;
+}
+
+export class ProjectOnboarding extends React.PureComponent<Props, State> {
+ mounted = false;
+ static contextTypes = {
+ router: PropTypes.object
+ };
+
+ constructor(props: Props) {
+ super(props);
+ this.state = {
+ finished: false,
+ step: props.organizationsEnabled ? 'organization' : 'token'
+ };
+ }
+
+ componentDidMount() {
+ this.mounted = true;
+
+ // useCapture = true to receive the event before inputs
+ window.addEventListener('keydown', this.onKeyDown, true);
+
+ if (!isLoggedIn(this.props.currentUser)) {
+ handleRequiredAuthentication();
+ }
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener('keydown', this.onKeyDown, true);
+ this.mounted = false;
+ }
+
+ onKeyDown = (event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ this.finishOnboarding();
+ }
+ };
+
+ finishOnboarding = () => {
+ this.props.onFinish();
+ if (this.state.projectKey) {
+ this.context.router.push(getProjectUrl(this.state.projectKey));
+ }
+ };
+
+ handleTimeout = () => {
+ // unset `projectKey` to display a generic "Finish this tutorial" button
+ this.setState({ projectKey: undefined });
+ };
+
+ handleTokenDone = (token: string) => {
+ this.setState({ step: 'analysis', token });
+ };
+
+ handleOrganizationDone = (organization: string) => {
+ this.setState({ organization, step: 'token' });
+ };
+
+ handleTokenOpen = () => this.setState({ step: 'token' });
+
+ handleOrganizationOpen = () => this.setState({ step: 'organization' });
+
+ handleFinish = (projectKey?: string) => this.setState({ finished: true, projectKey });
+
+ handleReset = () => this.setState({ finished: false, projectKey: undefined });
+
+ render() {
+ const { automatic, currentUser, organizationsEnabled } = this.props;
+ if (!isLoggedIn(currentUser)) {
+ return null;
+ }
+
+ const { finished, projectKey, step, token } = this.state;
+ const header = translate('onboarding.project.header');
+ let stepNumber = 1;
+
+ return (
+ <>
+ <Helmet title={header} titleTemplate="%s" />
+ <header className="modal-head">
+ <h2>{header}</h2>
+ </header>
+ <div className="modal-body modal-container">
+ <p className="spacer-top big-spacer-bottom">
+ {translateWithParameters(
+ 'onboarding.project.header.description',
+ organizationsEnabled ? 3 : 2
+ )}
+ </p>
+ {organizationsEnabled && (
+ <OrganizationStep
+ currentUser={currentUser}
+ finished={this.state.organization != null}
+ onContinue={this.handleOrganizationDone}
+ onOpen={this.handleOrganizationOpen}
+ open={step === 'organization'}
+ stepNumber={stepNumber++}
+ />
+ )}
+
+ <TokenStep
+ currentUser={currentUser}
+ finished={this.state.token != null}
+ onContinue={this.handleTokenDone}
+ onOpen={this.handleTokenOpen}
+ open={step === 'token'}
+ stepNumber={stepNumber++}
+ />
+
+ <AnalysisStep
+ onFinish={this.handleFinish}
+ onReset={this.handleReset}
+ open={step === 'analysis'}
+ organization={this.state.organization}
+ stepNumber={stepNumber}
+ token={token}
+ />
+ </div>
+ <footer className="modal-foot">
+ <ResetButtonLink className="js-skip" onClick={this.finishOnboarding}>
+ {(finished && translate('tutorials.finish')) ||
+ (automatic ? translate('tutorials.skip') : translate('close'))}
+ </ResetButtonLink>
+ {finished && projectKey ? (
+ <ProjectWatcher
+ onFinish={this.finishOnboarding}
+ onTimeout={this.handleTimeout}
+ projectKey={projectKey}
+ />
+ ) : (
+ <span className="pull-left note">
+ {translate(
+ isSonarCloud()
+ ? 'tutorials.find_tutorial_back_in_plus'
+ : 'tutorials.find_tutorial_back_in_help'
+ )}
+ </span>
+ )}
+ </footer>
+ </>
+ );
+ }
+}
+
+const mapStateToProps = (state: any): StateProps => {
+ return {
+ currentUser: getCurrentUser(state),
+ organizationsEnabled: areThereCustomOrganizations(state)
+ };
+};
+
+export default connect<StateProps, {}, OwnProps>(mapStateToProps)(ProjectOnboarding);
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboardingModal.tsx
index 188e5cc7927..d91e78872f4 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboardingModal.tsx
@@ -27,12 +27,12 @@ interface Props {
onFinish: () => void;
}
-const OnboardingContainer = lazyLoad(() => import('./OnboardingContainer'));
+const ProjectOnboarding = lazyLoad(() => import('./ProjectOnboarding'));
-export default function OnboardingModal(props: Props) {
+export default function ProjectOnboardingModal(props: Props) {
return (
<Modal contentLabel={translate('tutorials.onboarding')} large={true}>
- <OnboardingContainer {...props} />
+ <ProjectOnboarding {...props} />
</Modal>
);
}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingPage.tsx b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboardingPage.tsx
index 971ae8bddff..5d0978e41d9 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingPage.tsx
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectOnboardingPage.tsx
@@ -20,14 +20,14 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import OnboardingModal from './OnboardingModal';
+import ProjectOnboardingModal from './ProjectOnboardingModal';
import { skipOnboarding } from '../../../store/users/actions';
interface DispatchProps {
skipOnboarding: () => void;
}
-export class OnboardingPage extends React.PureComponent<DispatchProps> {
+export class ProjectOnboardingPage extends React.PureComponent<DispatchProps> {
static contextTypes = {
router: PropTypes.object.isRequired
};
@@ -38,10 +38,10 @@ export class OnboardingPage extends React.PureComponent<DispatchProps> {
};
render() {
- return <OnboardingModal onFinish={this.onSkipOnboardingTutorial} />;
+ return <ProjectOnboardingModal onFinish={this.onSkipOnboardingTutorial} />;
}
}
const mapDispatchToProps: DispatchProps = { skipOnboarding };
-export default connect<{}, DispatchProps, {}>(null, mapDispatchToProps)(OnboardingPage);
+export default connect<{}, DispatchProps>(null, mapDispatchToProps)(ProjectOnboardingPage);
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectWatcher.tsx
index e836e988fbe..31683d2f4cd 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/ProjectWatcher.tsx
@@ -17,8 +17,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
+import * as classNames from 'classnames';
import AlertErrorIcon from '../../../components/icons-components/AlertErrorIcon';
import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessIcon';
import { getTasksForComponent } from '../../../api/ce';
@@ -28,35 +29,27 @@ import { translate } from '../../../helpers/l10n';
const INTERVAL = 5000;
const TIMEOUT = 10 * 60 * 1000; // 10 min
-/*::
-type Props = {
- onFinish: () => void,
- onTimeout: () => void,
- projectKey: string
-};
-*/
+interface Props {
+ onFinish: () => void;
+ onTimeout: () => void;
+ projectKey: string;
+}
-/*::
-type State = {
- inQueue: boolean,
- status: ?string
-};
-*/
+interface State {
+ inQueue: boolean;
+ status?: string;
+}
-export default class ProjectWatcher extends React.PureComponent {
- /*:: interval: number; */
- /*:: mounted: boolean; */
- /*:: props: Props; */
- /*:: timeout: number; */
- state /*: State */ = {
- inQueue: false,
- status: null
- };
+export default class ProjectWatcher extends React.PureComponent<Props, State> {
+ interval?: number;
+ timeout?: number;
+ mounted = false;
+ state: State = { inQueue: false };
componentDidMount() {
this.mounted = true;
this.watch();
- this.timeout = setTimeout(this.props.onTimeout, TIMEOUT);
+ this.timeout = window.setTimeout(this.props.onTimeout, TIMEOUT);
}
componentWillUnmount() {
@@ -65,7 +58,7 @@ export default class ProjectWatcher extends React.PureComponent {
this.mounted = false;
}
- watch = () => (this.interval = setTimeout(this.checkProject, INTERVAL));
+ watch = () => (this.interval = window.setTimeout(this.checkProject, INTERVAL));
checkProject = () => {
const { projectKey } = this.props;
@@ -93,10 +86,11 @@ export default class ProjectWatcher extends React.PureComponent {
render() {
const { inQueue, status } = this.state;
+ const className = 'pull-left note';
if (status === STATUSES.SUCCESS) {
return (
- <div className="big-spacer-top note text-center">
+ <div className={classNames(className, 'display-inline-flex-center')}>
<AlertSuccessIcon className="spacer-right" />
{translate('onboarding.project_watcher.finished')}
</div>
@@ -105,7 +99,7 @@ export default class ProjectWatcher extends React.PureComponent {
if (inQueue || status === STATUSES.PENDING || status === STATUSES.IN_PROGRESS) {
return (
- <div className="big-spacer-top note text-center">
+ <div className={className}>
<i className="spinner spacer-right" />
{translate('onboarding.project_watcher.in_progress')}
</div>
@@ -114,17 +108,13 @@ export default class ProjectWatcher extends React.PureComponent {
if (status != null) {
return (
- <div className="big-spacer-top note text-center">
+ <div className={classNames(className, 'display-inline-flex-center')}>
<AlertErrorIcon className="spacer-right" />
{translate('onboarding.project_watcher.failed')}
</div>
);
}
- return (
- <div className="big-spacer-top note text-center">
- {translate('onboarding.project_watcher.not_started')}
- </div>
- );
+ return <div className={className}>{translate('onboarding.project_watcher.not_started')}</div>;
}
}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/Step.tsx
index d9f6394a75f..7fda3877528 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/Step.tsx
@@ -17,23 +17,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
-import classNames from 'classnames';
+/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/no-noninteractive-tabindex */
+import * as React from 'react';
+import * as classNames from 'classnames';
-/*::
-type Props = {|
- finished: boolean,
- onOpen: () => void,
- open: boolean,
- renderForm: () => React.Element<*>,
- renderResult: () => ?React.Element<*>,
- stepNumber: number,
- stepTitle: React.Element<*> | string
-|};
-*/
+interface Props {
+ finished: boolean;
+ onOpen: () => void;
+ open: boolean;
+ renderForm: () => React.ReactNode;
+ renderResult: () => React.ReactNode;
+ stepNumber: number;
+ stepTitle: React.ReactNode;
+}
-export default function Step(props /*: Props */) {
+export default function Step(props: Props) {
const className = classNames('boxed-group', 'onboarding-step', {
'is-open': props.open,
'is-finished': props.finished
@@ -41,7 +39,7 @@ export default function Step(props /*: Props */) {
const clickable = !props.open && props.finished;
- const handleClick = (event /*: Event */) => {
+ const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
props.onOpen();
};
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/TokenStep.tsx
index 6ef86cd7b3a..e0cd2c5aacc 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/TokenStep.tsx
@@ -17,9 +17,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
-import classNames from 'classnames';
+
+import * as React from 'react';
+import * as classNames from 'classnames';
import Step from './Step';
import { getTokens, generateToken, revokeToken } from '../../../api/user-tokens';
import AlertErrorIcon from '../../../components/icons-components/AlertErrorIcon';
@@ -27,32 +27,28 @@ import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessI
import { DeleteButton, SubmitButton, Button } from '../../../components/ui/buttons';
import { translate } from '../../../helpers/l10n';
-/*::
-type Props = {|
- currentUser: { login: string },
- finished: boolean,
- open: boolean,
- onContinue: (token: string) => void,
- onOpen: () => void,
- stepNumber: number
-|};
-*/
+interface Props {
+ currentUser: { login: string };
+ finished: boolean;
+ open: boolean;
+ onContinue: (token: string) => void;
+ onOpen: () => void;
+ stepNumber: number;
+}
-/*::
-type State = {
- canUseExisting: boolean,
- existingToken: string,
- loading: boolean,
- selection: string,
- tokenName?: string,
- token?: string
-};
-*/
+interface State {
+ canUseExisting: boolean;
+ existingToken: string;
+ loading: boolean;
+ selection: string;
+ tokenName?: string;
+ token?: string;
+}
-export default class TokenStep extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
+export default class TokenStep extends React.PureComponent<Props, State> {
+ mounted = false;
+
+ state: State = {
canUseExisting: false,
existingToken: '',
loading: false,
@@ -87,27 +83,20 @@ export default class TokenStep extends React.PureComponent {
);
};
- handleTokenNameChange = (event /*: { target: HTMLInputElement } */) => {
+ handleTokenNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ tokenName: event.target.value });
};
- handleTokenGenerate = (event /*: Event */) => {
+ handleTokenGenerate = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { tokenName } = this.state;
if (tokenName) {
this.setState({ loading: true });
- generateToken({ name: tokenName }).then(
- ({ token }) => {
- if (this.mounted) {
- this.setState({ loading: false, token });
- }
- },
- () => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
+ generateToken({ name: tokenName }).then(({ token }) => {
+ if (this.mounted) {
+ this.setState({ loading: false, token });
}
- );
+ }, this.stopLoading);
}
};
@@ -115,18 +104,11 @@ export default class TokenStep extends React.PureComponent {
const { tokenName } = this.state;
if (tokenName) {
this.setState({ loading: true });
- revokeToken({ name: tokenName }).then(
- () => {
- if (this.mounted) {
- this.setState({ loading: false, token: undefined, tokenName: undefined });
- }
- },
- () => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
+ revokeToken({ name: tokenName }).then(() => {
+ if (this.mounted) {
+ this.setState({ loading: false, token: undefined, tokenName: undefined });
}
- );
+ }, this.stopLoading);
}
};
@@ -137,20 +119,26 @@ export default class TokenStep extends React.PureComponent {
}
};
- handleGenerateClick = (event /*: Event */) => {
+ handleGenerateClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.setState({ selection: 'generate' });
};
- handleUseExistingClick = (event /*: Event */) => {
+ handleUseExistingClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.setState({ selection: 'use-existing' });
};
- handleExisingTokenChange = (event /*: { currentTarget: HTMLInputElement } */) => {
+ handleExisingTokenChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ existingToken: event.currentTarget.value });
};
+ stopLoading = () => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ };
+
renderGenerateOption = () => (
<div>
{this.state.canUseExisting ? (
@@ -163,10 +151,10 @@ export default class TokenStep extends React.PureComponent {
'is-checked': this.state.selection === 'generate'
})}
/>
- {translate('onboading.token.generate_token')}
+ {translate('onboarding.token.generate_token')}
</a>
) : (
- translate('onboading.token.generate_token')
+ translate('onboarding.token.generate_token')
)}
{this.state.selection === 'generate' && (
<div className="big-spacer-top">
@@ -175,7 +163,7 @@ export default class TokenStep extends React.PureComponent {
autoFocus={true}
className="input-large spacer-right text-middle"
onChange={this.handleTokenNameChange}
- placeholder={translate('onboading.token.generate_token.placeholder')}
+ placeholder={translate('onboarding.token.generate_token.placeholder')}
required={true}
type="text"
value={this.state.tokenName || ''}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/LanguageStep-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/LanguageStep-test.tsx
index 2609b550dd5..629044f2c4c 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/LanguageStep-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/LanguageStep-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { shallow } from 'enzyme';
import LanguageStep from '../LanguageStep';
import { isSonarCloud } from '../../../../helpers/system';
@@ -26,29 +25,29 @@ import { isSonarCloud } from '../../../../helpers/system';
jest.mock('../../../../helpers/system', () => ({ isSonarCloud: jest.fn() }));
beforeEach(() => {
- isSonarCloud.mockImplementation(() => false);
+ (isSonarCloud as jest.Mock<any>).mockImplementation(() => false);
});
it('selects java', () => {
const onDone = jest.fn();
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />);
- wrapper.find('RadioToggle').prop('onCheck')('java');
+ (wrapper.find('RadioToggle').prop('onCheck') as Function)('java');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper
+ (wrapper
.find('RadioToggle')
.at(1)
- .prop('onCheck')('maven');
+ .prop('onCheck') as Function)('maven');
wrapper.update();
expect(wrapper).toMatchSnapshot();
expect(onDone).lastCalledWith({ language: 'java', javaBuild: 'maven' });
- wrapper
+ (wrapper
.find('RadioToggle')
.at(1)
- .prop('onCheck')('gradle');
+ .prop('onCheck') as Function)('gradle');
wrapper.update();
expect(wrapper).toMatchSnapshot();
expect(onDone).lastCalledWith({ language: 'java', javaBuild: 'gradle' });
@@ -58,52 +57,52 @@ it('selects c#', () => {
const onDone = jest.fn();
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />);
- wrapper.find('RadioToggle').prop('onCheck')('dotnet');
+ (wrapper.find('RadioToggle').prop('onCheck') as Function)('dotnet');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper.find('NewProjectForm').prop('onDone')('project-foo');
+ (wrapper.find('NewProjectForm').prop('onDone') as Function)('project-foo');
expect(onDone).lastCalledWith({ language: 'dotnet', projectKey: 'project-foo' });
});
it('selects c-family', () => {
- isSonarCloud.mockImplementation(() => true);
+ (isSonarCloud as jest.Mock<any>).mockImplementation(() => true);
const onDone = jest.fn();
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />);
- wrapper.find('RadioToggle').prop('onCheck')('c-family');
+ (wrapper.find('RadioToggle').prop('onCheck') as Function)('c-family');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper
+ (wrapper
.find('RadioToggle')
.at(1)
- .prop('onCheck')('msvc');
+ .prop('onCheck') as Function)('msvc');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper.find('NewProjectForm').prop('onDone')('project-foo');
+ (wrapper.find('NewProjectForm').prop('onDone') as Function)('project-foo');
expect(onDone).lastCalledWith({
language: 'c-family',
cFamilyCompiler: 'msvc',
projectKey: 'project-foo'
});
- wrapper
+ (wrapper
.find('RadioToggle')
.at(1)
- .prop('onCheck')('clang-gcc');
+ .prop('onCheck') as Function)('clang-gcc');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper
+ (wrapper
.find('RadioToggle')
.at(2)
- .prop('onCheck')('linux');
+ .prop('onCheck') as Function)('linux');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper.find('NewProjectForm').prop('onDone')('project-foo');
+ (wrapper.find('NewProjectForm').prop('onDone') as Function)('project-foo');
expect(onDone).lastCalledWith({
language: 'c-family',
cFamilyCompiler: 'clang-gcc',
@@ -116,17 +115,17 @@ it('selects other', () => {
const onDone = jest.fn();
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />);
- wrapper.find('RadioToggle').prop('onCheck')('other');
+ (wrapper.find('RadioToggle').prop('onCheck') as Function)('other');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper
+ (wrapper
.find('RadioToggle')
.at(1)
- .prop('onCheck')('mac');
+ .prop('onCheck') as Function)('mac');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- wrapper.find('NewProjectForm').prop('onDone')('project-foo');
+ (wrapper.find('NewProjectForm').prop('onDone') as Function)('project-foo');
expect(onDone).lastCalledWith({ language: 'other', os: 'mac', projectKey: 'project-foo' });
});
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/NewOrganizationForm-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/NewOrganizationForm-test.tsx
index fcfbf8d810c..bb16f901167 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/NewOrganizationForm-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/NewOrganizationForm-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { mount } from 'enzyme';
import NewOrganizationForm from '../NewOrganizationForm';
import { change, submit, waitAndUpdate } from '../../../../helpers/testUtils';
@@ -48,7 +47,7 @@ it('deletes organization', async () => {
const wrapper = mount(<NewOrganizationForm onDelete={onDelete} onDone={jest.fn()} />);
wrapper.setState({ done: true, loading: false, organization: 'foo' });
expect(wrapper).toMatchSnapshot();
- wrapper.find('DeleteButton').prop('onClick')();
+ (wrapper.find('DeleteButton').prop('onClick') as Function)();
wrapper.update();
expect(wrapper).toMatchSnapshot(); // spinner
await waitAndUpdate(wrapper);
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/NewProjectForm-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/NewProjectForm-test.tsx
index 2d290f10503..2c8c18cace4 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/NewProjectForm-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/NewProjectForm-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { mount } from 'enzyme';
import NewProjectForm from '../NewProjectForm';
import { change, submit, waitAndUpdate } from '../../../../helpers/testUtils';
@@ -47,7 +46,7 @@ it('deletes project', async () => {
const wrapper = mount(<NewProjectForm onDelete={onDelete} onDone={jest.fn()} />);
wrapper.setState({ done: true, loading: false, projectKey: 'foo' });
expect(wrapper).toMatchSnapshot();
- wrapper.find('DeleteButton').prop('onClick')();
+ (wrapper.find('DeleteButton').prop('onClick') as Function)();
wrapper.update();
expect(wrapper).toMatchSnapshot(); // spinner
await waitAndUpdate(wrapper);
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/OrganizationStep-test.tsx
index 01a5b711a2a..b2192a0bce7 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/OrganizationStep-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { mount } from 'enzyme';
import OrganizationStep from '../OrganizationStep';
import { click, waitAndUpdate } from '../../../../helpers/testUtils';
@@ -35,7 +34,7 @@ jest.mock('../../../../api/organizations', () => ({
const currentUser = { isLoggedIn: true, login: 'user' };
beforeEach(() => {
- getOrganizations.mockClear();
+ (getOrganizations as jest.Mock<any>).mockClear();
});
// FIXME
@@ -73,10 +72,10 @@ it('works with existing organization', async () => {
await waitAndUpdate(wrapper);
click(wrapper.find('.js-existing'));
expect(wrapper).toMatchSnapshot();
- wrapper
+ (wrapper
.find('Select')
.first()
- .prop('onChange')({ value: 'another' });
+ .prop('onChange') as Function)({ value: 'another' });
wrapper.update();
click(wrapper.find('[className="js-continue"]'));
expect(onContinue).toBeCalledWith('another');
@@ -96,7 +95,7 @@ it('works with new organization', async () => {
);
await waitAndUpdate(wrapper);
click(wrapper.find('.js-new'));
- wrapper.find('NewOrganizationForm').prop('onDone')('new');
+ (wrapper.find('NewOrganizationForm').prop('onDone') as Function)('new');
wrapper.update();
click(wrapper.find('[className="js-continue"]'));
expect(onContinue).toBeCalledWith('new');
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/ProjectOnboarding-test.tsx
index e3acb2a83f6..078d6702aa6 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/ProjectOnboarding-test.tsx
@@ -17,10 +17,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { shallow, mount } from 'enzyme';
-import Onboarding from '../Onboarding';
+import { ProjectOnboarding } from '../ProjectOnboarding';
import { click, doAsync } from '../../../../helpers/testUtils';
import { getInstance, isSonarCloud } from '../../../../helpers/system';
@@ -36,11 +35,10 @@ jest.mock('../../../../helpers/system', () => ({
const currentUser = { login: 'admin', isLoggedIn: true };
it('guides for on-premise', () => {
- getInstance.mockImplementation(() => 'SonarQube');
- isSonarCloud.mockImplementation(() => false);
+ (getInstance as jest.Mock<any>).mockImplementation(() => 'SonarQube');
+ (isSonarCloud as jest.Mock<any>).mockImplementation(() => false);
const wrapper = shallow(
- <Onboarding
- className="modal-container"
+ <ProjectOnboarding
currentUser={currentUser}
onFinish={jest.fn()}
organizationsEnabled={false}
@@ -48,39 +46,36 @@ it('guides for on-premise', () => {
);
expect(wrapper).toMatchSnapshot();
- // $FlowFixMe
- wrapper.instance().handleTokenDone('abcd1234');
+ (wrapper.instance() as ProjectOnboarding).handleTokenDone('abcd1234');
wrapper.update();
expect(wrapper).toMatchSnapshot();
});
it('guides for sonarcloud', () => {
- getInstance.mockImplementation(() => 'SonarCloud');
- isSonarCloud.mockImplementation(() => true);
+ (getInstance as jest.Mock<any>).mockImplementation(() => 'SonarCloud');
+ (isSonarCloud as jest.Mock<any>).mockImplementation(() => true);
const wrapper = shallow(
- <Onboarding currentUser={currentUser} onFinish={jest.fn()} organizationsEnabled={true} />
+ <ProjectOnboarding currentUser={currentUser} onFinish={jest.fn()} organizationsEnabled={true} />
);
expect(wrapper).toMatchSnapshot();
- // $FlowFixMe
- wrapper.instance().handleOrganizationDone('my-org');
+ (wrapper.instance() as ProjectOnboarding).handleOrganizationDone('my-org');
wrapper.update();
expect(wrapper).toMatchSnapshot();
- // $FlowFixMe
- wrapper.instance().handleTokenDone('abcd1234');
+ (wrapper.instance() as ProjectOnboarding).handleTokenDone('abcd1234');
wrapper.update();
expect(wrapper).toMatchSnapshot();
});
it('finishes', () => {
- getInstance.mockImplementation(() => 'SonarQube');
- isSonarCloud.mockImplementation(() => false);
+ (getInstance as jest.Mock<any>).mockImplementation(() => 'SonarQube');
+ (isSonarCloud as jest.Mock<any>).mockImplementation(() => false);
const onFinish = jest.fn();
const wrapper = mount(
- <Onboarding currentUser={currentUser} onFinish={onFinish} organizationsEnabled={false} />
+ <ProjectOnboarding currentUser={currentUser} onFinish={onFinish} organizationsEnabled={false} />
);
- click(wrapper.find('.js-skip'));
+ click(wrapper.find('ResetButtonLink'));
return doAsync(() => {
expect(onFinish).toBeCalled();
});
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/ProjectWatcher-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/ProjectWatcher-test.tsx
index cc6699fdefa..16215259325 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/ProjectWatcher-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/ProjectWatcher-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { shallow, mount } from 'enzyme';
import ProjectWatcher from '../ProjectWatcher';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Step-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/Step-test.tsx
index 396c4fa769a..8a9664f71c8 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Step-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/Step-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { shallow } from 'enzyme';
import Step from '../Step';
import { click } from '../../../../helpers/testUtils';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/TokenStep-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/TokenStep-test.tsx
index 4f439b440b5..25b5f0c7462 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/TokenStep-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/TokenStep-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { mount } from 'enzyme';
import TokenStep from '../TokenStep';
import { change, click, submit, waitAndUpdate } from '../../../../helpers/testUtils';
@@ -67,7 +66,7 @@ it('revokes token', async () => {
await new Promise(setImmediate);
wrapper.setState({ token: 'abcd1234', tokenName: 'my token' });
expect(wrapper).toMatchSnapshot();
- wrapper.find('DeleteButton').prop('onClick')();
+ (wrapper.find('DeleteButton').prop('onClick') as Function)();
wrapper.update();
expect(wrapper).toMatchSnapshot(); // spinner
await waitAndUpdate(wrapper);
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/LanguageStep-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/LanguageStep-test.tsx.snap
index 8e82d384b3f..8e82d384b3f 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/LanguageStep-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/LanguageStep-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/NewOrganizationForm-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/NewOrganizationForm-test.tsx.snap
index eae8fcdb833..eae8fcdb833 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/NewOrganizationForm-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/NewOrganizationForm-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/NewProjectForm-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/NewProjectForm-test.tsx.snap
index f6722a21bf6..f6722a21bf6 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/NewProjectForm-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/NewProjectForm-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/OrganizationStep-test.tsx.snap
index 7e30dedc4a9..7e30dedc4a9 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/OrganizationStep-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectOnboarding-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectOnboarding-test.tsx.snap
new file mode 100644
index 00000000000..0c5b93e108a
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectOnboarding-test.tsx.snap
@@ -0,0 +1,349 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`guides for on-premise 1`] = `
+<React.Fragment>
+ <HelmetWrapper
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="onboarding.project.header"
+ titleTemplate="%s"
+ />
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.project.header
+ </h2>
+ </header>
+ <div
+ className="modal-body modal-container"
+ >
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.project.header.description.2
+ </p>
+ <TokenStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={false}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={true}
+ stepNumber={1}
+ />
+ <AnalysisStep
+ onFinish={[Function]}
+ onReset={[Function]}
+ open={false}
+ stepNumber={2}
+ />
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ className="js-skip"
+ onClick={[Function]}
+ >
+ close
+ </ResetButtonLink>
+ <span
+ className="pull-left note"
+ >
+ tutorials.find_tutorial_back_in_help
+ </span>
+ </footer>
+</React.Fragment>
+`;
+
+exports[`guides for on-premise 2`] = `
+<React.Fragment>
+ <HelmetWrapper
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="onboarding.project.header"
+ titleTemplate="%s"
+ />
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.project.header
+ </h2>
+ </header>
+ <div
+ className="modal-body modal-container"
+ >
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.project.header.description.2
+ </p>
+ <TokenStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={true}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={false}
+ stepNumber={1}
+ />
+ <AnalysisStep
+ onFinish={[Function]}
+ onReset={[Function]}
+ open={true}
+ stepNumber={2}
+ token="abcd1234"
+ />
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ className="js-skip"
+ onClick={[Function]}
+ >
+ close
+ </ResetButtonLink>
+ <span
+ className="pull-left note"
+ >
+ tutorials.find_tutorial_back_in_help
+ </span>
+ </footer>
+</React.Fragment>
+`;
+
+exports[`guides for sonarcloud 1`] = `
+<React.Fragment>
+ <HelmetWrapper
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="onboarding.project.header"
+ titleTemplate="%s"
+ />
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.project.header
+ </h2>
+ </header>
+ <div
+ className="modal-body modal-container"
+ >
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.project.header.description.3
+ </p>
+ <OrganizationStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={false}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={true}
+ stepNumber={1}
+ />
+ <TokenStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={false}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={false}
+ stepNumber={2}
+ />
+ <AnalysisStep
+ onFinish={[Function]}
+ onReset={[Function]}
+ open={false}
+ stepNumber={3}
+ />
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ className="js-skip"
+ onClick={[Function]}
+ >
+ close
+ </ResetButtonLink>
+ <span
+ className="pull-left note"
+ >
+ tutorials.find_tutorial_back_in_plus
+ </span>
+ </footer>
+</React.Fragment>
+`;
+
+exports[`guides for sonarcloud 2`] = `
+<React.Fragment>
+ <HelmetWrapper
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="onboarding.project.header"
+ titleTemplate="%s"
+ />
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.project.header
+ </h2>
+ </header>
+ <div
+ className="modal-body modal-container"
+ >
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.project.header.description.3
+ </p>
+ <OrganizationStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={true}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={false}
+ stepNumber={1}
+ />
+ <TokenStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={false}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={true}
+ stepNumber={2}
+ />
+ <AnalysisStep
+ onFinish={[Function]}
+ onReset={[Function]}
+ open={false}
+ organization="my-org"
+ stepNumber={3}
+ />
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ className="js-skip"
+ onClick={[Function]}
+ >
+ close
+ </ResetButtonLink>
+ <span
+ className="pull-left note"
+ >
+ tutorials.find_tutorial_back_in_plus
+ </span>
+ </footer>
+</React.Fragment>
+`;
+
+exports[`guides for sonarcloud 3`] = `
+<React.Fragment>
+ <HelmetWrapper
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="onboarding.project.header"
+ titleTemplate="%s"
+ />
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.project.header
+ </h2>
+ </header>
+ <div
+ className="modal-body modal-container"
+ >
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.project.header.description.3
+ </p>
+ <OrganizationStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={true}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={false}
+ stepNumber={1}
+ />
+ <TokenStep
+ currentUser={
+ Object {
+ "isLoggedIn": true,
+ "login": "admin",
+ }
+ }
+ finished={true}
+ onContinue={[Function]}
+ onOpen={[Function]}
+ open={false}
+ stepNumber={2}
+ />
+ <AnalysisStep
+ onFinish={[Function]}
+ onReset={[Function]}
+ open={true}
+ organization="my-org"
+ stepNumber={3}
+ token="abcd1234"
+ />
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ className="js-skip"
+ onClick={[Function]}
+ >
+ close
+ </ResetButtonLink>
+ <span
+ className="pull-left note"
+ >
+ tutorials.find_tutorial_back_in_plus
+ </span>
+ </footer>
+</React.Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/ProjectWatcher-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectWatcher-test.tsx.snap
index 4ecd80c2ae3..1cc4d9991f6 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/ProjectWatcher-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/ProjectWatcher-test.tsx.snap
@@ -2,7 +2,7 @@
exports[`renders 1`] = `
<div
- className="big-spacer-top note text-center"
+ className="pull-left note"
>
onboarding.project_watcher.not_started
</div>
@@ -10,7 +10,7 @@ exports[`renders 1`] = `
exports[`renders 2`] = `
<div
- className="big-spacer-top note text-center"
+ className="pull-left note"
>
<i
className="spinner spacer-right"
@@ -21,7 +21,7 @@ exports[`renders 2`] = `
exports[`renders 3`] = `
<div
- className="big-spacer-top note text-center"
+ className="pull-left note display-inline-flex-center"
>
<AlertSuccessIcon
className="spacer-right"
@@ -32,7 +32,7 @@ exports[`renders 3`] = `
exports[`renders 4`] = `
<div
- className="big-spacer-top note text-center"
+ className="pull-left note"
>
<i
className="spinner spacer-right"
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Step-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/Step-test.tsx.snap
index 4667ca7ae8a..4667ca7ae8a 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Step-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/Step-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/TokenStep-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/TokenStep-test.tsx.snap
index 9b991a92305..54847972e8c 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/TokenStep-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/__tests__/__snapshots__/TokenStep-test.tsx.snap
@@ -50,7 +50,7 @@ exports[`generates token 1`] = `
<i
className="icon-radio spacer-right is-checked"
/>
- onboading.token.generate_token
+ onboarding.token.generate_token
</a>
<div
className="big-spacer-top"
@@ -62,7 +62,7 @@ exports[`generates token 1`] = `
autoFocus={true}
className="input-large spacer-right text-middle"
onChange={[Function]}
- placeholder="onboading.token.generate_token.placeholder"
+ placeholder="onboarding.token.generate_token.placeholder"
required={true}
type="text"
value=""
@@ -166,7 +166,7 @@ exports[`generates token 2`] = `
<i
className="icon-radio spacer-right is-checked"
/>
- onboading.token.generate_token
+ onboarding.token.generate_token
</a>
<div
className="big-spacer-top"
@@ -178,7 +178,7 @@ exports[`generates token 2`] = `
autoFocus={true}
className="input-large spacer-right text-middle"
onChange={[Function]}
- placeholder="onboading.token.generate_token.placeholder"
+ placeholder="onboarding.token.generate_token.placeholder"
required={true}
type="text"
value="my token"
@@ -582,7 +582,7 @@ exports[`revokes token 3`] = `
<i
className="icon-radio spacer-right is-checked"
/>
- onboading.token.generate_token
+ onboarding.token.generate_token
</a>
<div
className="big-spacer-top"
@@ -594,7 +594,7 @@ exports[`revokes token 3`] = `
autoFocus={true}
className="input-large spacer-right text-middle"
onChange={[Function]}
- placeholder="onboading.token.generate_token.placeholder"
+ placeholder="onboarding.token.generate_token.placeholder"
required={true}
type="text"
value=""
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/BuildWrapper.tsx
index 47fe5202388..ed03adbf911 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/BuildWrapper.tsx
@@ -17,24 +17,22 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { translate } from '../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../helpers/urls';
-/*::
-type Props = {
- className?: string,
- os: string
-};
-*/
+interface Props {
+ className?: string;
+ os: string;
+}
-const filenames = {
+const filenames: { [key: string]: string } = {
win: 'build-wrapper-win-x86.zip',
linux: 'build-wrapper-linux-x86.zip',
mac: 'build-wrapper-macosx-x86.zip'
};
-export default function BuildWrapper(props /*: Props */) {
+export default function BuildWrapper(props: Props) {
return (
<div className={props.className}>
<h4 className="spacer-bottom">
@@ -50,7 +48,7 @@ export default function BuildWrapper(props /*: Props */) {
<a
className="button"
download={filenames[props.os]}
- href={window.baseUrl + '/static/cpp/' + filenames[props.os]}
+ href={`${getBaseUrl()}/static/cpp/${filenames[props.os]}`}
target="_blank">
{translate('download_verb')}
</a>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/ClangGCC.tsx
index 0c1fdab16cf..6ebe42a3ca9 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/ClangGCC.tsx
@@ -17,31 +17,28 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import SQScanner from './SQScanner';
import BuildWrapper from './BuildWrapper';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {
- host: string,
- os: string,
- organization?: string,
- projectKey: string,
- token: string
-};
-*/
+interface Props {
+ host: string;
+ os: string;
+ organization?: string;
+ projectKey: string;
+ token: string;
+}
-const executables = {
+const executables: { [key: string]: string } = {
linux: 'build-wrapper-linux-x86-64',
win: 'build-wrapper-win-x86-64.exe',
mac: 'build-wrapper-macosx-x86'
};
-export default function ClangGCC(props /*: Props */) {
+export default function ClangGCC(props: Props) {
const command1 = `${executables[props.os]} --out-dir bw-output make clean all`;
const command2 = [
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/DotNet.tsx
index a5bd3fd4285..347ea01b7ac 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/DotNet.tsx
@@ -17,23 +17,20 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import MSBuildScanner from './MSBuildScanner';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {|
- host: string,
- organization?: string,
- projectKey: string,
- token: string
-|};
-*/
+interface Props {
+ host: string;
+ organization?: string;
+ projectKey: string;
+ token: string;
+}
-export default function DotNet(props /*: Props */) {
+export default function DotNet(props: Props) {
const command1 = [
'SonarQube.Scanner.MSBuild.exe begin',
`/k:"${props.projectKey}"`,
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/JavaGradle.tsx
index d3cc1c847da..02da9fd1a2a 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/JavaGradle.tsx
@@ -17,21 +17,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {|
- host: string,
- organization?: string,
- token: string
-|};
-*/
+interface Props {
+ host: string;
+ organization?: string;
+ token: string;
+}
-export default function JavaGradle(props /*: Props */) {
+export default function JavaGradle(props: Props) {
const config = 'plugins {\n id "org.sonarqube" version "2.6"\n}';
const command = [
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/JavaMaven.tsx
index 8a02fb75630..5663b1f2911 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/JavaMaven.tsx
@@ -17,21 +17,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {|
- host: string,
- organization?: string,
- token: string
-|};
-*/
+interface Props {
+ host: string;
+ organization?: string;
+ token: string;
+}
-export default function JavaMaven(props /*: Props */) {
+export default function JavaMaven(props: Props) {
const command = [
'mvn sonar:sonar',
props.organization && `-Dsonar.organization=${props.organization}`,
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/MSBuildScanner.tsx
index af0ade047c3..65c4005af86 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/MSBuildScanner.tsx
@@ -17,17 +17,15 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {
- className?: string
-};
-*/
+interface Props {
+ className?: string;
+}
-export default function MSBuildScanner(props /*: Props */) {
+export default function MSBuildScanner(props: Props) {
return (
<div className={props.className}>
<h4 className="spacer-bottom">{translate('onboarding.analysis.msbuild.header')}</h4>
@@ -39,6 +37,7 @@ export default function MSBuildScanner(props /*: Props */) {
<a
className="button"
href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html"
+ rel="noopener noreferrer"
target="_blank">
{translate('download_verb')}
</a>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/Msvc.tsx
index 03f5fe3eb63..cf6120a3b31 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/Msvc.tsx
@@ -17,24 +17,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import MSBuildScanner from './MSBuildScanner';
import BuildWrapper from './BuildWrapper';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {|
- host: string,
- organization?: string,
- projectKey: string,
- token: string
-|};
-*/
+interface Props {
+ host: string;
+ organization?: string;
+ projectKey: string;
+ token: string;
+}
-export default function Msvc(props /*: Props */) {
+export default function Msvc(props: Props) {
const command1 = [
'SonarQube.Scanner.MSBuild.exe begin',
`/k:"${props.projectKey}"`,
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/Other.tsx
index 5bb0d0dd649..3d0b3b2a718 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/Other.tsx
@@ -17,24 +17,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import SQScanner from './SQScanner';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {|
- host: string,
- organization?: string,
- os: string,
- projectKey: string,
- token: string
-|};
-*/
+interface Props {
+ host: string;
+ organization?: string;
+ os: string;
+ projectKey: string;
+ token: string;
+}
-export default function Other(props /*: Props */) {
+export default function Other(props: Props) {
const command = [
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner',
`-Dsonar.projectKey=${props.projectKey}`,
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/SQScanner.tsx
index 3fd3e3e9711..78b90f851bc 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/SQScanner.tsx
@@ -17,18 +17,16 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { translate } from '../../../../helpers/l10n';
-/*::
-type Props = {
- className?: string,
- os: string
-};
-*/
+interface Props {
+ className?: string;
+ os: string;
+}
-export default function SQScanner(props /*: Props */) {
+export default function SQScanner(props: Props) {
return (
<div className={props.className}>
<h4 className="spacer-bottom">
@@ -44,6 +42,7 @@ export default function SQScanner(props /*: Props */) {
<a
className="button"
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
+ rel="noopener noreferrer"
target="_blank">
{translate('download_verb')}
</a>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/BuildWrapper-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/BuildWrapper-test.tsx
index 4d3f979b3c8..b19e334793b 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/BuildWrapper-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/BuildWrapper-test.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { shallow } from 'enzyme';
import BuildWrapper from '../BuildWrapper';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/ClangGCC-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/ClangGCC-test.tsx
index 9f8f9243da5..a6f7c4f550a 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/ClangGCC-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/ClangGCC-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import ClangGCC from '../ClangGCC';
@@ -35,8 +35,8 @@ it('renders correctly', () => {
shallow(
<ClangGCC
host="host"
- os="linux"
organization="organization"
+ os="linux"
projectKey="projectKey"
token="token"
/>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/DotNet-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/DotNet-test.tsx
index b9dc347956a..91ecab828b2 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/DotNet-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/DotNet-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import DotNet from '../DotNet';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/JavaGradle-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/JavaGradle-test.tsx
index bfddcc9c728..f0d130a248d 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/JavaGradle-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/JavaGradle-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import JavaGradle from '../JavaGradle';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/JavaMaven-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/JavaMaven-test.tsx
index 592e578b3bc..dbda16ca13e 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/JavaMaven-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/JavaMaven-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import JavaMaven from '../JavaMaven';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/MSBuildScanner-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/MSBuildScanner-test.tsx
index 5551fcead5c..e5411341d10 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/MSBuildScanner-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/MSBuildScanner-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import MSBuildScanner from '../MSBuildScanner';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/Msvc-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/Msvc-test.tsx
index 62ccf801fb9..78470bbd2e6 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/Msvc-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/Msvc-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import Msvc from '../Msvc';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/Other-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/Other-test.tsx
index b7175078c96..16cc44ae69f 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/Other-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/Other-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import Other from '../Other';
@@ -35,8 +35,8 @@ it('renders correctly', () => {
shallow(
<Other
host="host"
- os="linux"
organization="organization"
+ os="linux"
projectKey="projectKey"
token="token"
/>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/SQScanner-test.js b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/SQScanner-test.tsx
index 11a0ccb58ad..2be4e546bb3 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/SQScanner-test.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/SQScanner-test.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+
+import * as React from 'react';
import { shallow } from 'enzyme';
import SQScanner from '../SQScanner';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/BuildWrapper-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap
index 07e8eb45f0a..07e8eb45f0a 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/BuildWrapper-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/ClangGCC-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap
index cdffd4c2061..cdffd4c2061 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/ClangGCC-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/DotNet-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/DotNet-test.tsx.snap
index 89b57fa28b4..89b57fa28b4 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/DotNet-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/DotNet-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/JavaGradle-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap
index 401137a9234..401137a9234 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/JavaGradle-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/JavaMaven-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap
index d4462b957c6..d4462b957c6 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/JavaMaven-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/MSBuildScanner-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap
index c7f156bc53f..740e26ed12b 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/MSBuildScanner-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap
@@ -19,6 +19,7 @@ exports[`renders correctly 1`] = `
<a
className="button"
href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html"
+ rel="noopener noreferrer"
target="_blank"
>
download_verb
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Msvc-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/Msvc-test.tsx.snap
index 2240a13995c..2240a13995c 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Msvc-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/Msvc-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Other-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/Other-test.tsx.snap
index 73aba357dca..73aba357dca 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Other-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/Other-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/SQScanner-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap
index bcdac075ce4..cf6a8de4ce3 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/SQScanner-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/projectOnboarding/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap
@@ -19,6 +19,7 @@ exports[`renders correctly 1`] = `
<a
className="button"
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
+ rel="noopener noreferrer"
target="_blank"
>
download_verb
@@ -46,6 +47,7 @@ exports[`renders correctly 2`] = `
<a
className="button"
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
+ rel="noopener noreferrer"
target="_blank"
>
download_verb
@@ -73,6 +75,7 @@ exports[`renders correctly 3`] = `
<a
className="button"
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
+ rel="noopener noreferrer"
target="_blank"
>
download_verb
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/styles.css b/server/sonar-web/src/main/js/apps/tutorials/styles.css
index 9c8dfc093fc..f73428e0f40 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/styles.css
+++ b/server/sonar-web/src/main/js/apps/tutorials/styles.css
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-.onboarding {
- min-height: calc(70vh - 60px);
-}
.onboarding-step {
position: relative;
@@ -58,12 +55,8 @@
outline: none;
}
-.onboarding .page-actions {
- text-align: right;
- margin-bottom: 0;
-}
-
-.onboarding .page-actions p {
- line-height: 16px;
- margin-top: 6px;
+.onboarding-choices {
+ display: flex;
+ justify-content: space-around;
+ padding: 24px 0 44px;
}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx
new file mode 100644
index 00000000000..0763e82b9ab
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx
@@ -0,0 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import Modal from '../../../components/controls/Modal';
+import { translate } from '../../../helpers/l10n';
+import { ResetButtonLink } from '../../../components/ui/buttons';
+
+interface Props {
+ onFinish: () => void;
+}
+
+export default class TeamOnboardingModal extends React.PureComponent<Props> {
+ render() {
+ const header = translate('onboarding.team.header');
+ return (
+ <Modal
+ contentLabel={header}
+ medium={true}
+ onRequestClose={this.props.onFinish}
+ shouldCloseOnOverlayClick={false}>
+ <header className="modal-head">
+ <h2>{header}</h2>
+ </header>
+ <div className="modal-body">
+ <div className="alert alert-info modal-alert">
+ {translate('onboarding.team.work_in_progress')}
+ </div>
+ <p className="spacer-top big-spacer-bottom">{translate('onboarding.team.first_step')}</p>
+ <p className="spacer-top big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={translate('onboarding.team.how_to_join')}
+ id="onboarding.team.how_to_join"
+ values={{
+ link: (
+ <Link onClick={this.props.onFinish} to="/documentation/organizations/manage-team">
+ {translate('as_explained_here')}
+ </Link>
+ )
+ }}
+ />
+ </p>
+ </div>
+ <footer className="modal-foot">
+ <ResetButtonLink onClick={this.props.onFinish}>{translate('close')}</ResetButtonLink>
+ </footer>
+ </Modal>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.d.ts b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/TeamOnboardingModal-test.tsx
index 4b70adcc600..0bd903f80f2 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.d.ts
+++ b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/TeamOnboardingModal-test.tsx
@@ -18,9 +18,9 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { shallow } from 'enzyme';
+import TeamOnboardingModal from '../TeamOnboardingModal';
-export interface Props {
- onFinish: () => void;
-}
-
-export default class OnboardingModal extends React.PureComponent<Props> {}
+it('renders correctly', () => {
+ expect(shallow(<TeamOnboardingModal onFinish={jest.fn()} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap
new file mode 100644
index 00000000000..a510b0e0eb9
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap
@@ -0,0 +1,61 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders correctly 1`] = `
+<Modal
+ contentLabel="onboarding.team.header"
+ medium={true}
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+>
+ <header
+ className="modal-head"
+ >
+ <h2>
+ onboarding.team.header
+ </h2>
+ </header>
+ <div
+ className="modal-body"
+ >
+ <div
+ className="alert alert-info modal-alert"
+ >
+ onboarding.team.work_in_progress
+ </div>
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ onboarding.team.first_step
+ </p>
+ <p
+ className="spacer-top big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.team.how_to_join"
+ id="onboarding.team.how_to_join"
+ values={
+ Object {
+ "link": <Link
+ onClick={[MockFunction]}
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/documentation/organizations/manage-team"
+ >
+ as_explained_here
+ </Link>,
+ }
+ }
+ />
+ </p>
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ close
+ </ResetButtonLink>
+ </footer>
+</Modal>
+`;