123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- * SonarQube
- * Copyright (C) 2009-2019 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 { OnboardingContext } from './OnboardingContext';
- import { differenceInDays, parseDate, toShortNotSoISOString } from '../../helpers/dates';
- import { getCurrentUser, getAppState, Store } from '../../store/rootReducer';
- import { skipOnboarding } from '../../store/users';
- import { showLicense } from '../../api/marketplace';
- import { hasMessage } from '../../helpers/l10n';
- import { save, get } from '../../helpers/storage';
- import { isSonarCloud } from '../../helpers/system';
- import { lazyLoad } from '../../components/lazyLoad';
- import { isLoggedIn } from '../../helpers/users';
- import { withRouter, Router, Location } from '../../components/hoc/withRouter';
-
- const OnboardingModal = lazyLoad(() => import('../../apps/tutorials/onboarding/OnboardingModal'));
- const LicensePromptModal = lazyLoad(
- () => import('../../apps/marketplace/components/LicensePromptModal'),
- 'LicensePromptModal'
- );
- const TeamOnboardingModal = lazyLoad(() =>
- import('../../apps/tutorials/teamOnboarding/TeamOnboardingModal')
- );
-
- interface StateProps {
- canAdmin?: boolean;
- currentEdition?: T.EditionKey;
- currentUser: T.CurrentUser;
- }
-
- interface DispatchProps {
- skipOnboarding: () => void;
- }
-
- interface OwnProps {
- children?: React.ReactNode;
- }
-
- interface WithRouterProps {
- location: Pick<Location, 'pathname'>;
- router: Pick<Router, 'push'>;
- }
-
- type Props = StateProps & DispatchProps & OwnProps & WithRouterProps;
-
- enum ModalKey {
- license,
- onboarding,
- teamOnboarding
- }
-
- interface State {
- modal?: ModalKey;
- }
-
- const LICENSE_PROMPT = 'sonarqube.license.prompt';
-
- export class StartupModal extends React.PureComponent<Props, State> {
- state: State = {};
-
- componentDidMount() {
- this.tryAutoOpenLicense().catch(this.tryAutoOpenOnboarding);
- }
-
- closeOnboarding = () => {
- this.setState(state => {
- if (state.modal !== ModalKey.license) {
- this.props.skipOnboarding();
- return { modal: undefined };
- }
- return null;
- });
- };
-
- closeLicense = () => {
- this.setState(state => {
- if (state.modal === ModalKey.license) {
- return { modal: undefined };
- }
- return null;
- });
- };
-
- openOnboarding = () => {
- this.setState({ modal: ModalKey.onboarding });
- };
-
- openProjectOnboarding = (organization?: T.Organization) => {
- this.setState({ modal: undefined });
- const state: { organization?: string; tab?: string } = {};
- if (organization) {
- state.organization = organization.key;
- state.tab = organization.alm ? 'auto' : 'manual';
- }
- this.props.router.push({ pathname: `/projects/create`, state });
- };
-
- openTeamOnboarding = () => {
- this.setState({ modal: ModalKey.teamOnboarding });
- };
-
- tryAutoOpenLicense = () => {
- const { canAdmin, currentEdition, currentUser } = this.props;
- const hasLicenseManager = hasMessage('license.prompt.title');
- const hasLicensedEdition = currentEdition && currentEdition !== 'community';
-
- if (canAdmin && hasLicensedEdition && isLoggedIn(currentUser) && hasLicenseManager) {
- const lastPrompt = get(LICENSE_PROMPT, currentUser.login);
-
- if (!lastPrompt || differenceInDays(new Date(), parseDate(lastPrompt)) >= 1) {
- return showLicense().then(license => {
- if (!license || !license.isValidEdition) {
- save(LICENSE_PROMPT, toShortNotSoISOString(new Date()), currentUser.login);
- this.setState({ modal: ModalKey.license });
- return Promise.resolve();
- }
- return Promise.reject();
- });
- }
- }
- return Promise.reject();
- };
-
- tryAutoOpenOnboarding = () => {
- if (
- isSonarCloud() &&
- this.props.currentUser.showOnboardingTutorial &&
- !['/about', '/documentation', '/onboarding', '/projects/create', '/create-organization'].some(
- path => this.props.location.pathname.startsWith(path)
- )
- ) {
- this.openOnboarding();
- }
- };
-
- render() {
- const { modal } = this.state;
- return (
- <OnboardingContext.Provider value={this.openProjectOnboarding}>
- {this.props.children}
- {modal === ModalKey.license && <LicensePromptModal onClose={this.closeLicense} />}
- {modal === ModalKey.onboarding && (
- <OnboardingModal
- onClose={this.closeOnboarding}
- onOpenProjectOnboarding={this.openProjectOnboarding}
- onOpenTeamOnboarding={this.openTeamOnboarding}
- />
- )}
- {modal === ModalKey.teamOnboarding && (
- <TeamOnboardingModal onFinish={this.closeOnboarding} />
- )}
- </OnboardingContext.Provider>
- );
- }
- }
-
- const mapStateToProps = (state: Store): StateProps => ({
- canAdmin: getAppState(state).canAdmin,
- currentEdition: getAppState(state).edition,
- currentUser: getCurrentUser(state)
- });
-
- const mapDispatchToProps: DispatchProps = { skipOnboarding };
-
- export default connect(
- mapStateToProps,
- mapDispatchToProps
- )(withRouter(StartupModal));
|