From: Wouter Admiraal Date: Fri, 17 Apr 2020 14:12:18 +0000 (+0200) Subject: Drop SonarCloud components from project creation app X-Git-Tag: 8.4.0.35506~237 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cd894cdb5e823472ed24b2669cfb8c04a4b69e74;p=sonarqube.git Drop SonarCloud components from project creation app --- diff --git a/server/sonar-web/src/main/js/apps/create/project/AlmRepositoryItem.tsx b/server/sonar-web/src/main/js/apps/create/project/AlmRepositoryItem.tsx deleted file mode 100644 index 2ee68b5bee2..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/AlmRepositoryItem.tsx +++ /dev/null @@ -1,123 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 classNames from 'classnames'; -import { identity } from 'lodash'; -import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { Link } from 'react-router'; -import Checkbox from 'sonar-ui-common/components/controls/Checkbox'; -import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; -import CheckIcon from 'sonar-ui-common/components/icons/CheckIcon'; -import LockIcon from 'sonar-ui-common/components/icons/LockIcon'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; -import { colors } from '../../../app/theme'; -import { getProjectUrl } from '../../../helpers/urls'; - -interface Props { - disabled: boolean; - highlightUpgradeBox: (highlight: boolean) => void; - identityProvider: T.IdentityProvider; - repository: T.AlmRepository; - selected: boolean; - toggleRepository: (repository: T.AlmRepository) => void; -} - -export default class AlmRepositoryItem extends React.PureComponent { - handleMouseEnter = () => { - this.props.highlightUpgradeBox(true); - }; - - handleMouseLeave = () => { - this.props.highlightUpgradeBox(false); - }; - - handleToggle = () => { - if (!this.props.disabled && !this.props.repository.linkedProjectKey) { - this.props.toggleRepository(this.props.repository); - } - }; - - render() { - const { disabled, identityProvider, repository, selected } = this.props; - const alreadyImported = Boolean(repository.linkedProjectKey); - return ( - -
  • -
    -
    - {disabled ? ( - - ) : ( - - )} - {identityProvider.name} - {this.props.repository.label} - {repository.private && ( -
    {translate('visibility.private')}
    - )} -
    - - {repository.linkedProjectKey && ( - - - - {translate('onboarding.create_project.see_project')} - - ) - }} - /> - - )} -
    -
  • -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/create/project/AutoProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/AutoProjectCreate.tsx deleted file mode 100644 index f57bf959cbc..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/AutoProjectCreate.tsx +++ /dev/null @@ -1,126 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 IdentityProviderLink from 'sonar-ui-common/components/controls/IdentityProviderLink'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { save } from 'sonar-ui-common/helpers/storage'; -import { - ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP, - ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP -} from '../organization/utils'; -import OrganizationInput from './OrganizationInput'; -import RemoteRepositories from './RemoteRepositories'; - -interface Props { - almApplication: T.AlmApplication; - boundOrganizations: T.Organization[]; - onOrganizationUpgrade: () => void; - onProjectCreate: (projectKeys: string[], organization: string) => void; - organization?: string; -} - -interface State { - selectedOrganization: string; -} - -export default class AutoProjectCreate extends React.PureComponent { - mounted = false; - - constructor(props: Props) { - super(props); - this.state = { selectedOrganization: this.getInitialSelectedOrganization(props) }; - } - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - getInitialSelectedOrganization(props: Props) { - if (props.organization) { - return props.organization; - } else if (props.boundOrganizations.length === 1) { - return props.boundOrganizations[0].key; - } else { - return ''; - } - } - - handleInstallAppClick = () => { - save(ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP, Date.now().toString(10)); - save(ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP, Date.now().toString(10)); - }; - - handleOrganizationSelect = ({ key }: T.Organization) => { - this.setState({ selectedOrganization: key }); - }; - - render() { - const { almApplication, boundOrganizations, onProjectCreate } = this.props; - - if (boundOrganizations.length === 0) { - return ( - <> -

    - {translate('onboarding.create_project.install_app_description', almApplication.key)} -

    - - {translate( - 'onboarding.import_organization.choose_organization_button', - almApplication.key - )} - - - ); - } - - const { selectedOrganization } = this.state; - const organization = boundOrganizations.find(o => o.key === selectedOrganization); - - return ( - <> - - {organization && ( - - )} - - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx index 3832019c27f..27822170748 100644 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx @@ -18,21 +18,141 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { Helmet } from 'react-helmet-async'; import { WithRouterProps } from 'react-router'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages'; +import { getAlmSettings } from '../../../api/alm-settings'; import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget'; -import { isSonarCloud } from '../../../helpers/system'; -import CreateProjectPageSonarCloud from './CreateProjectPageSonarCloud'; -import CreateProjectPageSonarQube from './CreateProjectPageSonarQube'; - -export default function CreateProjectPage(props: WithRouterProps) { - return ( - <> - - {isSonarCloud() ? ( - - ) : ( - - )} - - ); +import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn'; +import { withAppState } from '../../../components/hoc/withAppState'; +import { getProjectUrl } from '../../../helpers/urls'; +import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; +import BitbucketProjectCreate from './BitbucketProjectCreate'; +import CreateProjectModeSelection from './CreateProjectModeSelection'; +import ManualProjectCreate from './ManualProjectCreate'; +import './style.css'; +import { CreateProjectModes } from './types'; + +interface Props extends Pick { + appState: Pick; + currentUser: T.LoggedInUser; +} + +interface State { + bitbucketSettings: AlmSettingsInstance[]; + loading: boolean; +} + +export class CreateProjectPage extends React.PureComponent { + mounted = false; + state: State = { bitbucketSettings: [], loading: false }; + + componentDidMount() { + const { + appState: { branchesEnabled }, + location + } = this.props; + this.mounted = true; + if (branchesEnabled) { + this.fetchAlmBindings(); + } + + if (location.query?.mode || !branchesEnabled) { + addWhitePageClass(); + } + } + + componentDidUpdate(prevProps: Props) { + if (this.props.location.query?.mode && !prevProps.location.query?.mode) { + addWhitePageClass(); + } else if (!this.props.location.query?.mode && prevProps.location.query?.mode) { + removeWhitePageClass(); + } + } + + componentWillUnmount() { + this.mounted = false; + removeWhitePageClass(); + } + + fetchAlmBindings = () => { + this.setState({ loading: true }); + getAlmSettings() + .then(almSettings => { + if (this.mounted) { + this.setState({ + bitbucketSettings: almSettings.filter(s => s.alm === AlmKeys.Bitbucket), + loading: false + }); + } + }) + .catch(() => { + if (this.mounted) { + this.setState({ loading: false }); + } + }); + }; + + handleProjectCreate = (projectKeys: string[]) => { + if (projectKeys.length === 1) { + this.props.router.push(getProjectUrl(projectKeys[0])); + } + }; + + handleModeSelect = (mode: CreateProjectModes) => { + const { router, location } = this.props; + router.push({ + pathname: location.pathname, + query: { mode } + }); + }; + + render() { + const { + appState: { branchesEnabled }, + currentUser, + location + } = this.props; + const { bitbucketSettings, loading } = this.state; + + const mode: CreateProjectModes | undefined = location.query?.mode; + const showManualForm = !branchesEnabled || mode === CreateProjectModes.Manual; + const showBBSForm = branchesEnabled && mode === CreateProjectModes.BitbucketServer; + + return ( + <> + + +
    + {!showBBSForm && !showManualForm && ( + + )} + + {showManualForm && ( + + )} + + {showBBSForm && ( + + )} +
    + + ); + } } + +export default whenLoggedIn(withAppState(CreateProjectPage)); diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageSonarCloud.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageSonarCloud.tsx deleted file mode 100644 index 35bd08cce28..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageSonarCloud.tsx +++ /dev/null @@ -1,184 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async'; -import { connect } from 'react-redux'; -import { WithRouterProps } from 'react-router'; -import Tabs from 'sonar-ui-common/components/controls/Tabs'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages'; -import { getAlmAppInfo } from '../../../api/alm-integration'; -import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn'; -import { withUserOrganizations } from '../../../components/hoc/withUserOrganizations'; -import { hasAdvancedALMIntegration } from '../../../helpers/almIntegrations'; -import { getOrganizationUrl, getProjectUrl } from '../../../helpers/urls'; -import { skipOnboarding } from '../../../store/users'; -import AutoProjectCreate from './AutoProjectCreate'; -import ManualProjectCreate from './ManualProjectCreate'; -import './style.css'; - -interface Props { - currentUser: T.LoggedInUser; - fetchMyOrganizations: () => Promise; - skipOnboarding: () => void; - userOrganizations: T.Organization[]; -} - -interface State { - almApplication?: T.AlmApplication; - loading: boolean; -} - -type TabKeys = 'auto' | 'manual'; - -interface LocationState { - organization?: string; - tab?: TabKeys; -} - -export class CreateProjectPageSonarCloud extends React.PureComponent< - Props & WithRouterProps, - State -> { - mounted = false; - state: State = { loading: true }; - - componentDidMount() { - this.mounted = true; - if (hasAdvancedALMIntegration(this.props.currentUser)) { - this.fetchAlmApplication(); - } else { - this.setState({ loading: false }); - } - addWhitePageClass(); - } - - componentWillUnmount() { - this.mounted = false; - removeWhitePageClass(); - } - - handleProjectCreate = (projectKeys: string[], organization?: string) => { - this.props.skipOnboarding(); - if (projectKeys.length > 1) { - this.props.router.push({ - pathname: (organization ? getOrganizationUrl(organization) : '') + '/projects' - }); - } else if (projectKeys.length === 1) { - this.props.router.push(getProjectUrl(projectKeys[0])); - } - }; - - fetchAlmApplication = () => { - return getAlmAppInfo().then( - ({ application }) => { - if (this.mounted) { - this.setState({ almApplication: application, loading: false }); - } - }, - () => { - if (this.mounted) { - this.setState({ loading: false }); - } - } - ); - }; - - onTabChange = (tab: TabKeys) => { - this.updateUrl({ tab }); - }; - - updateUrl = (state: Partial = {}) => { - this.props.router.replace({ - pathname: this.props.location.pathname, - query: this.props.location.query, - state: { ...(this.props.location.state || {}), ...state } - }); - }; - - render() { - const { currentUser, location, userOrganizations } = this.props; - const { almApplication, loading } = this.state; - const state: LocationState = location.state || {}; - const header = translate('onboarding.create_project.header'); - const showManualTab = state.tab === 'manual'; - - return ( - <> - -
    -
    -

    - {header} -

    -
    - {loading ? ( - - ) : ( - <> - {almApplication && ( - - onChange={this.onTabChange} - selected={state.tab || 'auto'} - tabs={[ - { - key: 'auto', - node: translate('onboarding.create_project.select_repositories') - }, - { key: 'manual', node: translate('onboarding.create_project.setup_manually') } - ]} - /> - )} - - {showManualTab || !almApplication ? ( - actions.provision - )} - /> - ) : ( - alm && actions.provision - )} - onOrganizationUpgrade={this.props.fetchMyOrganizations} - onProjectCreate={this.handleProjectCreate} - organization={state.organization} - /> - )} - - )} -
    - - ); - } -} - -const mapDispatchToProps = { skipOnboarding }; - -export default whenLoggedIn( - withUserOrganizations(connect(null, mapDispatchToProps)(CreateProjectPageSonarCloud)) -); diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageSonarQube.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageSonarQube.tsx deleted file mode 100644 index d9a7c160070..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageSonarQube.tsx +++ /dev/null @@ -1,156 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async'; -import { WithRouterProps } from 'react-router'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages'; -import { getAlmSettings } from '../../../api/alm-settings'; -import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn'; -import { withAppState } from '../../../components/hoc/withAppState'; -import { getProjectUrl } from '../../../helpers/urls'; -import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; -import BitbucketProjectCreate from './BitbucketProjectCreate'; -import CreateProjectModeSelection from './CreateProjectModeSelection'; -import ManualProjectCreate from './ManualProjectCreate'; -import './style.css'; -import { CreateProjectModes } from './types'; - -interface Props extends Pick { - appState: Pick; - currentUser: T.LoggedInUser; -} - -interface State { - bitbucketSettings: AlmSettingsInstance[]; - loading: boolean; -} - -export class CreateProjectPageSonarQube extends React.PureComponent { - mounted = false; - state: State = { bitbucketSettings: [], loading: false }; - - componentDidMount() { - const { - appState: { branchesEnabled }, - location - } = this.props; - this.mounted = true; - if (branchesEnabled) { - this.fetchAlmBindings(); - } - - if (location.query?.mode || !branchesEnabled) { - addWhitePageClass(); - } - } - - componentDidUpdate(prevProps: Props) { - if (this.props.location.query?.mode && !prevProps.location.query?.mode) { - addWhitePageClass(); - } else if (!this.props.location.query?.mode && prevProps.location.query?.mode) { - removeWhitePageClass(); - } - } - - componentWillUnmount() { - this.mounted = false; - removeWhitePageClass(); - } - - fetchAlmBindings = () => { - this.setState({ loading: true }); - getAlmSettings() - .then(almSettings => { - if (this.mounted) { - this.setState({ - bitbucketSettings: almSettings.filter(s => s.alm === AlmKeys.Bitbucket), - loading: false - }); - } - }) - .catch(() => { - if (this.mounted) { - this.setState({ loading: false }); - } - }); - }; - - handleProjectCreate = (projectKeys: string[]) => { - if (projectKeys.length === 1) { - this.props.router.push(getProjectUrl(projectKeys[0])); - } - }; - - handleModeSelect = (mode: CreateProjectModes) => { - const { router, location } = this.props; - router.push({ - pathname: location.pathname, - query: { mode } - }); - }; - - render() { - const { - appState: { branchesEnabled }, - currentUser, - location - } = this.props; - const { bitbucketSettings, loading } = this.state; - - const mode: CreateProjectModes | undefined = location.query?.mode; - const showManualForm = !branchesEnabled || mode === CreateProjectModes.Manual; - const showBBSForm = branchesEnabled && mode === CreateProjectModes.BitbucketServer; - - return ( - <> - -
    - {!showBBSForm && !showManualForm && ( - - )} - - {showManualForm && ( - - )} - - {showBBSForm && ( - - )} -
    - - ); - } -} - -export default whenLoggedIn(withAppState(CreateProjectPageSonarQube)); diff --git a/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx index b14cf5d70da..1cb5f7f93b4 100644 --- a/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx @@ -25,19 +25,13 @@ import ValidationInput from 'sonar-ui-common/components/controls/ValidationInput import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { createProject, doesComponentExists } from '../../../api/components'; -import { isSonarCloud } from '../../../helpers/system'; -import UpgradeOrganizationBox from '../components/UpgradeOrganizationBox'; import CreateProjectPageHeader from './CreateProjectPageHeader'; import './ManualProjectCreate.css'; -import OrganizationInput from './OrganizationInput'; interface Props { branchesEnabled?: boolean; currentUser: T.LoggedInUser; - fetchMyOrganizations?: () => Promise; onProjectCreate: (projectKeys: string[]) => void; - organization?: string; - userOrganizations?: T.Organization[]; } interface State { @@ -46,8 +40,6 @@ interface State { projectNameError?: string; projectKey: string; projectKeyError?: string; - selectedOrganization?: T.Organization; - selectedVisibility?: T.Visibility; submitting: boolean; touched: boolean; validating: boolean; @@ -64,7 +56,6 @@ export default class ManualProjectCreate extends React.PureComponent { - return Boolean(selectedOrganization && selectedOrganization.subscription === 'PAID'); - }; - canSubmit(state: State): state is ValidState { - const { - projectKey, - projectKeyError, - projectName, - projectNameError, - selectedOrganization - } = state; + const { projectKey, projectKeyError, projectName, projectNameError } = state; return Boolean( projectKeyError === undefined && projectNameError === undefined && projectKey.length > 0 && - projectName.length > 0 && - (!isSonarCloud() || selectedOrganization) + projectName.length > 0 ); } - getInitialSelectedOrganization = (props: Props) => { - if (props.organization) { - return this.getOrganization(props.organization); - } else if (props.userOrganizations && props.userOrganizations.length === 1) { - return props.userOrganizations[0]; - } else { - return undefined; - } - }; - - getOrganization = (organizationKey: string) => { - return ( - this.props.userOrganizations && - this.props.userOrganizations.find(({ key }: T.Organization) => key === organizationKey) - ); - }; - handleFormSubmit = (event: React.FormEvent) => { event.preventDefault(); const { state } = this; @@ -147,9 +110,7 @@ export default class ManualProjectCreate extends React.PureComponent this.props.onProjectCreate([project.key]), () => { @@ -161,37 +122,6 @@ export default class ManualProjectCreate extends React.PureComponent { - const selectedOrganization = this.getOrganization(key); - let { selectedVisibility } = this.state; - - if (selectedVisibility === undefined) { - selectedVisibility = this.canChoosePrivate(selectedOrganization) ? 'private' : 'public'; - } - - this.setState({ - selectedOrganization, - selectedVisibility - }); - }; - - handleOrganizationUpgrade = () => { - this.props.fetchMyOrganizations!().then( - () => { - this.setState(prevState => { - if (prevState.selectedOrganization) { - const selectedOrganization = this.getOrganization(prevState.selectedOrganization.key); - return { - selectedOrganization - }; - } - return null; - }); - }, - () => {} - ); - }; - handleProjectKeyChange = (event: React.ChangeEvent) => { const projectKey = event.currentTarget.value || ''; const projectKeyError = this.validateKey(projectKey); @@ -222,10 +152,6 @@ export default class ManualProjectCreate extends React.PureComponent { - this.setState({ selectedVisibility }); - }; - validateKey = (projectKey: string) => { return projectKey.length > 400 || !/^[\w-.:]*[a-zA-Z]+[\w-.:]*$/.test(projectKey) ? translate('onboarding.create_project.project_key.error') @@ -244,7 +170,6 @@ export default class ManualProjectCreate extends React.PureComponent @@ -263,17 +187,9 @@ export default class ManualProjectCreate extends React.PureComponent -
    +
    - {isSonarCloud() && this.props.userOrganizations && ( - - )} -
    - - {isSonarCloud() && selectedOrganization && ( -
    - -
    - )}
    ); diff --git a/server/sonar-web/src/main/js/apps/create/project/OrganizationInput.tsx b/server/sonar-web/src/main/js/apps/create/project/OrganizationInput.tsx deleted file mode 100644 index a688284afd5..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/OrganizationInput.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { withRouter, WithRouterProps } from 'react-router'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { save } from 'sonar-ui-common/helpers/storage'; -import OrganizationSelect from '../components/OrganizationSelect'; -import { ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP } from '../organization/utils'; - -interface Props { - autoImport?: boolean; - onChange: (organization: T.Organization) => void; - organization: string; - organizations: T.Organization[]; -} - -export class OrganizationInput extends React.PureComponent { - handleLinkClick = (event: React.MouseEvent) => { - event.preventDefault(); - event.stopPropagation(); - save(ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP, Date.now().toString(10)); - this.props.router.push({ - pathname: '/create-organization', - state: { tab: this.props.autoImport ? 'auto' : 'manual' } - }); - }; - - render() { - const { autoImport, onChange, organization, organizations } = this.props; - return ( - - ); - } -} - -export default withRouter(OrganizationInput); diff --git a/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx b/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx deleted file mode 100644 index 2dd6437bac5..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx +++ /dev/null @@ -1,260 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 classNames from 'classnames'; -import { keyBy } from 'lodash'; -import * as React from 'react'; -import Checkbox from 'sonar-ui-common/components/controls/Checkbox'; -import SearchBox from 'sonar-ui-common/components/controls/SearchBox'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import { isDefined } from 'sonar-ui-common/helpers/types'; -import { getRepositories } from '../../../api/alm-integration'; -import { isPaidOrganization } from '../../../helpers/organizations'; -import UpgradeOrganizationBox from '../components/UpgradeOrganizationBox'; -import AlmRepositoryItem from './AlmRepositoryItem'; -import SetupProjectBox from './SetupProjectBox'; - -interface Props { - almApplication: T.AlmApplication; - onOrganizationUpgrade: () => void; - onProjectCreate: (projectKeys: string[], organization: string) => void; - organization: T.Organization; -} - -type SelectedRepositories = T.Dict; - -interface State { - checkAllRepositories: boolean; - highlight: boolean; - loading: boolean; - repositories: T.AlmRepository[]; - search: string; - selectedRepositories: SelectedRepositories; - successfullyUpgraded: boolean; -} - -export default class RemoteRepositories extends React.PureComponent { - mounted = false; - state: State = { - checkAllRepositories: false, - highlight: false, - loading: true, - repositories: [], - search: '', - selectedRepositories: {}, - successfullyUpgraded: false - }; - - componentDidMount() { - this.mounted = true; - this.fetchRepositories(); - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.organization.key !== this.props.organization.key) { - this.setState({ loading: true, selectedRepositories: {} }); - this.fetchRepositories(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchRepositories = () => { - const { organization } = this.props; - return getRepositories({ organization: organization.key }).then( - ({ repositories }) => { - if (this.mounted) { - this.setState({ loading: false, repositories }); - } - }, - () => { - if (this.mounted) { - this.setState({ loading: false }); - } - } - ); - }; - - filterBySearch = (search: String) => (repo: T.AlmRepository) => { - return repo.label.toLowerCase().includes(search.toLowerCase()); - }; - - handleHighlightUpgradeBox = (highlight: boolean) => { - this.setState({ highlight }); - }; - - handleOrganizationUpgrade = () => { - this.props.onOrganizationUpgrade(); - if (this.mounted) { - this.setState({ successfullyUpgraded: true }); - } - }; - - handleProvisionFail = () => { - return this.fetchRepositories().then(() => { - if (this.mounted) { - this.setState(({ repositories, selectedRepositories }) => { - const updateSelectedRepositories: SelectedRepositories = {}; - Object.keys(selectedRepositories).forEach(installationKey => { - const newRepository = repositories.find(r => r.installationKey === installationKey); - if (newRepository && !newRepository.linkedProjectKey) { - updateSelectedRepositories[newRepository.installationKey] = newRepository; - } - }); - return { selectedRepositories: updateSelectedRepositories }; - }); - } - }); - }; - - handleSearch = (search: string) => { - this.setState({ search, checkAllRepositories: false, selectedRepositories: {} }); - }; - - onCheckAllRepositories = () => { - this.setState(({ checkAllRepositories, repositories, search }) => { - const { organization } = this.props; - - const isPaidOrg = isPaidOrganization(organization); - const filterByPlan = (repo: T.AlmRepository) => (isPaidOrg ? true : !repo.private); - const filterByImportable = (repo: T.AlmRepository) => !repo.linkedProjectKey; - - const nextState = { - selectedRepositories: {}, - checkAllRepositories: !checkAllRepositories - }; - - if (nextState.checkAllRepositories) { - const validRepositories = repositories.filter( - repo => - this.filterBySearch(search)(repo) && filterByPlan(repo) && filterByImportable(repo) - ); - nextState.selectedRepositories = keyBy(validRepositories, 'installationKey'); - } - - return nextState; - }); - }; - - toggleRepository = (repository: T.AlmRepository) => { - this.setState(({ selectedRepositories }) => ({ - selectedRepositories: { - ...selectedRepositories, - [repository.installationKey]: selectedRepositories[repository.installationKey] - ? undefined - : repository - } - })); - }; - - render() { - const { highlight, loading, repositories, search, selectedRepositories } = this.state; - const { almApplication, organization } = this.props; - const isPaidOrg = isPaidOrganization(organization); - const hasPrivateRepositories = repositories.some(repository => Boolean(repository.private)); - const showSearchBox = repositories.length > 5; - const showCheckAll = repositories.length > 1; - const showUpgradebox = - !isPaidOrg && hasPrivateRepositories && organization.actions && organization.actions.admin; - const filteredRepositories = repositories.filter(this.filterBySearch(search)); - - return ( -
    -
    -
    -
    - {showCheckAll && ( - - {translate('onboarding.create_project.select_all_repositories')} - - )} -
    - {showSearchBox && ( - - )} -
    - - {this.state.successfullyUpgraded && ( - - {translateWithParameters( - 'onboarding.create_project.subscribtion_success_x', - organization.name - )} - - )} - -
      - {filteredRepositories.length === 0 && ( -
    • - {showUpgradebox - ? translateWithParameters('no_results_for_x', search) - : translate('onboarding.create_project.no_repositories')} -
    • - )} - {filteredRepositories.map(repo => ( - - ))} -
    -
    -
    - {organization && ( -
    -
    - selectedRepositories[r]) - .filter(isDefined)} - /> - {showUpgradebox && ( - - )} -
    -
    - )} -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/create/project/SetupProjectBox.tsx b/server/sonar-web/src/main/js/apps/create/project/SetupProjectBox.tsx deleted file mode 100644 index a9add273696..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/SetupProjectBox.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 classNames from 'classnames'; -import { partition } from 'lodash'; -import * as React from 'react'; -import { SubmitButton } from 'sonar-ui-common/components/controls/buttons'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import { provisionProject } from '../../../api/alm-integration'; - -interface Props { - onProjectCreate: (projectKeys: string[], organization: string) => void; - onProvisionFail: () => Promise; - organization: T.Organization; - selectedRepositories: T.AlmRepository[]; -} - -interface State { - submitting: boolean; -} - -export default class SetupProjectBox extends React.PureComponent { - mounted = false; - state: State = { submitting: false }; - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - canSubmit = () => { - return !this.state.submitting && this.props.selectedRepositories.length > 0; - }; - - handleFormSubmit = (event: React.FormEvent) => { - event.preventDefault(); - - if (this.canSubmit()) { - const { selectedRepositories } = this.props; - this.setState({ submitting: true }); - provisionProject({ - installationKeys: selectedRepositories.map(repo => repo.installationKey), - organization: this.props.organization.key - }).then( - ({ projects }) => - this.props.onProjectCreate( - projects.map(project => project.projectKey), - this.props.organization.key - ), - this.handleProvisionFail - ); - } - }; - - handleProvisionFail = () => { - return this.props.onProvisionFail().then(() => { - if (this.mounted) { - this.setState({ submitting: false }); - } - }); - }; - - render() { - const { selectedRepositories } = this.props; - const hasSelectedRepositories = selectedRepositories.length > 0; - const [privateRepos = [], publicRepos = []] = partition( - selectedRepositories, - repo => repo.private - ); - return ( -
    -
    -

    - {selectedRepositories.length > 1 - ? translateWithParameters( - 'onboarding.create_project.x_repositories_selected', - selectedRepositories.length - ) - : translate('onboarding.create_project.1_repository_selected')} -

    -
    -
    -
    - {publicRepos.length === 1 && ( -

    {translate('onboarding.create_project.1_repository_created_as_public')}

    - )} - {publicRepos.length > 1 && ( -

    - {translateWithParameters( - 'onboarding.create_project.x_repository_created_as_public', - publicRepos.length - )} -

    - )} - {privateRepos.length === 1 && ( -

    {translate('onboarding.create_project.1_repository_created_as_private')}

    - )} - {privateRepos.length > 1 && ( -

    - {translateWithParameters( - 'onboarding.create_project.x_repository_created_as_private', - privateRepos.length - )} -

    - )} -
    -
    - - {translate('set_up')} - - -
    -
    -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/AlmRepositoryItem-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/AlmRepositoryItem-test.tsx deleted file mode 100644 index 3690840552e..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/AlmRepositoryItem-test.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import AlmRepositoryItem from '../AlmRepositoryItem'; - -const identityProviders = { - backgroundColor: 'blue', - iconPath: 'icon/path', - key: 'foo', - name: 'Foo Provider' -}; - -const repositories = [ - { - label: 'Cool Project', - installationKey: 'github/cool', - linkedProjectKey: 'proj_cool', - linkedProjectName: 'Proj Cool' - }, - { - label: 'Awesome Project', - installationKey: 'github/awesome' - } -]; - -it('should render correctly', () => { - expect(getWrapper()).toMatchSnapshot(); -}); - -it('should render selected', () => { - expect(getWrapper({ selected: true })).toMatchSnapshot(); -}); - -it('should render imported', () => { - expect(getWrapper({ repository: repositories[0] })).toMatchSnapshot(); -}); - -it('should render disabed', () => { - expect(getWrapper({ disabled: true, repository: repositories[1] })).toMatchSnapshot(); -}); - -it('should render private repositories', () => { - expect(getWrapper({ repository: { ...repositories[1], private: true } })).toMatchSnapshot(); -}); - -function getWrapper(props = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/AutoProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/AutoProjectCreate-test.tsx deleted file mode 100644 index b3439293278..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/AutoProjectCreate-test.tsx +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { - mockOrganizationWithAdminActions, - mockOrganizationWithAlm -} from '../../../../helpers/testMocks'; -import AutoProjectCreate from '../AutoProjectCreate'; - -const almApplication = { - backgroundColor: 'blue', - iconPath: 'icon/path', - installationUrl: 'https://alm.installation.url', - key: 'github', - name: 'GitHub' -}; - -const boundOrganizations: T.Organization[] = [ - mockOrganizationWithAdminActions(mockOrganizationWithAlm({ subscription: 'FREE' })), - mockOrganizationWithAlm({ key: 'bar', name: 'Bar', subscription: 'FREE' }) -]; - -it('should display the provider app install button', () => { - expect(shallowRender({ boundOrganizations: [] })).toMatchSnapshot(); -}); - -it('should display the bound organizations dropdown with the remote repositories', () => { - expect(shallowRender({ organization: 'foo' })).toMatchSnapshot(); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx index 067da27aaa7..6ed0a1e9459 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx @@ -17,34 +17,68 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + import { shallow } from 'enzyme'; import * as React from 'react'; -import { isSonarCloud } from '../../../../helpers/system'; -import { mockLocation, mockRouter } from '../../../../helpers/testMocks'; -import CreateProjectPage from '../CreateProjectPage'; +import { addWhitePageClass } from 'sonar-ui-common/helpers/pages'; +import { getAlmSettings } from '../../../../api/alm-settings'; +import { mockLocation, mockLoggedInUser, mockRouter } from '../../../../helpers/testMocks'; +import { AlmKeys } from '../../../../types/alm-settings'; +import { CreateProjectPage } from '../CreateProjectPage'; +import { CreateProjectModes } from '../types'; + +jest.mock('../../../../api/alm-settings', () => ({ + getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.Bitbucket, key: 'foo' }]) +})); -jest.mock('../../../../helpers/system', () => ({ - isSonarCloud: jest.fn().mockReturnValue(false) +jest.mock('sonar-ui-common/helpers/pages', () => ({ + addWhitePageClass: jest.fn(), + removeWhitePageClass: jest.fn() })); -it('should render correctly for SonarQube', () => { - const wrapper = shallowRender(); - expect(wrapper).toMatchSnapshot(); +beforeEach(jest.clearAllMocks); + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); + expect(getAlmSettings).toBeCalled(); +}); + +it('should render correctly if no branch support', () => { + expect(shallowRender({ appState: { branchesEnabled: false } })).toMatchSnapshot(); + expect(getAlmSettings).not.toBeCalled(); }); -it('should render correctly for SonarCloud', () => { - (isSonarCloud as jest.Mock).mockReturnValue(true); - const wrapper = shallowRender(); - expect(wrapper).toMatchSnapshot(); +it('should render correctly if the manual method is selected', () => { + const push = jest.fn(); + const location = { query: { mode: CreateProjectModes.Manual } }; + const wrapper = shallowRender({ router: mockRouter({ push }) }); + + wrapper.instance().handleModeSelect(CreateProjectModes.Manual); + expect(push).toBeCalledWith(expect.objectContaining(location)); + + expect(wrapper.setProps({ location: mockLocation(location) })).toMatchSnapshot(); + expect(addWhitePageClass).toBeCalled(); +}); + +it('should render correctly if the BBS method is selected', () => { + const push = jest.fn(); + const location = { query: { mode: CreateProjectModes.BitbucketServer } }; + const wrapper = shallowRender({ router: mockRouter({ push }) }); + + wrapper.instance().handleModeSelect(CreateProjectModes.BitbucketServer); + expect(push).toBeCalledWith(expect.objectContaining(location)); + + expect(wrapper.setProps({ location: mockLocation(location) })).toMatchSnapshot(); + expect(addWhitePageClass).toBeCalled(); }); -function shallowRender(props = {}) { - return shallow( +function shallowRender(props: Partial = {}) { + return shallow( ); diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPageSonarCloud-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPageSonarCloud-test.tsx deleted file mode 100644 index 67788031ac1..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPageSonarCloud-test.tsx +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import { getAlmAppInfo } from '../../../../api/alm-integration'; -import { - mockOrganizationWithAdminActions, - mockOrganizationWithAlm, - mockRouter -} from '../../../../helpers/testMocks'; -import { CreateProjectPageSonarCloud } from '../CreateProjectPageSonarCloud'; - -jest.mock('../../../../api/alm-integration', () => ({ - getAlmAppInfo: jest.fn().mockResolvedValue({ - application: { - backgroundColor: 'blue', - iconPath: 'icon/path', - installationUrl: 'https://alm.installation.url', - key: 'github', - name: 'GitHub' - } - }) -})); - -const user: T.LoggedInUser = { - externalProvider: 'github', - groups: [], - isLoggedIn: true, - login: 'foo', - name: 'Foo', - scmAccounts: [] -}; - -beforeEach(() => { - (getAlmAppInfo as jest.Mock).mockClear(); -}); - -it('should render correctly', async () => { - const wrapper = getWrapper(); - expect(wrapper).toMatchSnapshot(); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); -}); - -it('should render with Custom creation only', () => { - expect(getWrapper({ currentUser: { ...user, externalProvider: 'microsoft' } })).toMatchSnapshot(); -}); - -it('should switch tabs', async () => { - const replace = jest.fn(); - const wrapper = getWrapper({ router: { replace } }); - replace.mockImplementation(location => { - wrapper.setProps({ location }).update(); - }); - - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); - - wrapper.find('Tabs').prop('onChange')('manual'); - expect(wrapper.find('ManualProjectCreate').exists()).toBe(true); - wrapper.find('Tabs').prop('onChange')('auto'); - expect(wrapper.find('AutoProjectCreate').exists()).toBe(true); -}); - -function getWrapper(props = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPageSonarQube-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPageSonarQube-test.tsx deleted file mode 100644 index e328df5b71a..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPageSonarQube-test.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { addWhitePageClass } from 'sonar-ui-common/helpers/pages'; -import { getAlmSettings } from '../../../../api/alm-settings'; -import { mockLocation, mockLoggedInUser, mockRouter } from '../../../../helpers/testMocks'; -import { AlmKeys } from '../../../../types/alm-settings'; -import { CreateProjectPageSonarQube } from '../CreateProjectPageSonarQube'; -import { CreateProjectModes } from '../types'; - -jest.mock('../../../../api/alm-settings', () => ({ - getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.Bitbucket, key: 'foo' }]) -})); - -jest.mock('sonar-ui-common/helpers/pages', () => ({ - addWhitePageClass: jest.fn(), - removeWhitePageClass: jest.fn() -})); - -beforeEach(jest.clearAllMocks); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect(getAlmSettings).toBeCalled(); -}); - -it('should render correctly if no branch support', () => { - expect(shallowRender({ appState: { branchesEnabled: false } })).toMatchSnapshot(); - expect(getAlmSettings).not.toBeCalled(); -}); - -it('should render correctly if the manual method is selected', () => { - const push = jest.fn(); - const location = { query: { mode: CreateProjectModes.Manual } }; - const wrapper = shallowRender({ router: mockRouter({ push }) }); - - wrapper.instance().handleModeSelect(CreateProjectModes.Manual); - expect(push).toBeCalledWith(expect.objectContaining(location)); - - expect(wrapper.setProps({ location: mockLocation(location) })).toMatchSnapshot(); - expect(addWhitePageClass).toBeCalled(); -}); - -it('should render correctly if the BBS method is selected', () => { - const push = jest.fn(); - const location = { query: { mode: CreateProjectModes.BitbucketServer } }; - const wrapper = shallowRender({ router: mockRouter({ push }) }); - - wrapper.instance().handleModeSelect(CreateProjectModes.BitbucketServer); - expect(push).toBeCalledWith(expect.objectContaining(location)); - - expect(wrapper.setProps({ location: mockLocation(location) })).toMatchSnapshot(); - expect(addWhitePageClass).toBeCalled(); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx index 0038bb8a37e..45d80de0668 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx @@ -43,10 +43,9 @@ it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); }); -it('should correctly create a public project', async () => { +it('should correctly create a project', async () => { const onProjectCreate = jest.fn(); const wrapper = shallowRender({ onProjectCreate }); - wrapper.find('withRouter(OrganizationInput)').prop('onChange')({ key: 'foo' }); change(wrapper.find('input#project-key'), 'bar'); change(wrapper.find('input#project-name'), 'Bar'); @@ -55,29 +54,7 @@ it('should correctly create a public project', async () => { submit(wrapper.find('form')); expect(createProject).toBeCalledWith({ project: 'bar', - name: 'Bar', - organization: 'foo', - visibility: 'public' - }); - - await waitAndUpdate(wrapper); - expect(onProjectCreate).toBeCalledWith(['bar']); -}); - -it('should correctly create a private project', async () => { - const onProjectCreate = jest.fn(); - const wrapper = shallowRender({ onProjectCreate }); - wrapper.find('withRouter(OrganizationInput)').prop('onChange')({ key: 'bar' }); - - change(wrapper.find('input#project-key'), 'bar'); - change(wrapper.find('input#project-name'), 'Bar'); - - submit(wrapper.find('form')); - expect(createProject).toBeCalledWith({ - project: 'bar', - name: 'Bar', - organization: 'bar', - visibility: 'private' + name: 'Bar' }); await waitAndUpdate(wrapper); @@ -157,12 +134,7 @@ function shallowRender(props: Partial = {}) { return shallow( ); diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/OrganizationInput-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/OrganizationInput-test.tsx deleted file mode 100644 index 31b6708c354..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/OrganizationInput-test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { - mockOrganization, - mockOrganizationWithAlm, - mockRouter -} from '../../../../helpers/testMocks'; -import { OrganizationInput } from '../OrganizationInput'; - -const organizations = [mockOrganization(), mockOrganizationWithAlm({ key: 'bar', name: 'Bar' })]; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect( - shallowRender({ autoImport: true }) - .find('.js-new-org') - .contains('onboarding.create_project.import_new_org') - ).toBe(true); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - // @ts-ignore avoid passing everything from WithRouterProps - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx deleted file mode 100644 index 15261cb9f78..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx +++ /dev/null @@ -1,151 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import { times } from 'lodash'; -import * as React from 'react'; -import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import { getRepositories } from '../../../../api/alm-integration'; -import { - mockOrganizationWithAdminActions, - mockOrganizationWithAlm -} from '../../../../helpers/testMocks'; -import RemoteRepositories from '../RemoteRepositories'; - -jest.mock('../../../../api/alm-integration', () => ({ - getRepositories: jest.fn().mockResolvedValue({ - repositories: [ - { - label: 'Cool Project', - installationKey: 'github/cool' - }, - { label: 'Awesome Project', installationKey: 'github/awesome' } - ] - }) -})); - -const almApplication = { - backgroundColor: 'blue', - iconPath: 'icon/path', - installationUrl: 'https://alm.installation.url', - key: 'github', - name: 'GitHub' -}; - -const organization: T.Organization = mockOrganizationWithAlm({ subscription: 'FREE' }); - -beforeEach(() => { - (getRepositories as jest.Mock).mockClear(); -}); - -it('should display the list of repositories', async () => { - const wrapper = shallowRender(); - expect(wrapper).toMatchSnapshot(); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); - expect(getRepositories).toHaveBeenCalledWith({ organization: 'foo' }); -}); - -it('should display the organization upgrade box', async () => { - (getRepositories as jest.Mock).mockResolvedValueOnce({ - repositories: [{ label: 'Foo Project', installationKey: 'github/foo', private: true }] - }); - const wrapper = shallowRender({ organization: { ...organization, actions: { admin: true } } }); - await waitAndUpdate(wrapper); - expect(wrapper.find('UpgradeOrganizationBox')).toMatchSnapshot(); - wrapper.find('UpgradeOrganizationBox').prop('onOrganizationUpgrade')(); - expect(wrapper.find('Alert[variant="success"]').exists()).toBe(true); -}); - -it('should not display the organization upgrade box', () => { - (getRepositories as jest.Mock).mockResolvedValueOnce({ - repositories: [{ label: 'Bar Project', installationKey: 'github/bar', private: true }] - }); - const wrapper = shallowRender({ - organization: mockOrganizationWithAdminActions( - mockOrganizationWithAlm({ subscription: 'PAID' }) - ) - }); - - expect(wrapper.find('UpgradeOrganizationBox').exists()).toBe(false); -}); - -it('should display a search box to filter repositories', async () => { - (getRepositories as jest.Mock).mockResolvedValueOnce({ - repositories: times(6, i => ({ label: `Project ${i}`, installationKey: `key-${i}` })) - }); - - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(wrapper.find('SearchBox').exists()).toBe(true); - expect(wrapper.find('AlmRepositoryItem')).toHaveLength(6); - wrapper.find('SearchBox').prop('onChange')('3'); - expect(wrapper.find('AlmRepositoryItem')).toHaveLength(1); -}); - -it('should allow to select all repositories', async () => { - (getRepositories as jest.Mock).mockResolvedValueOnce({ - repositories: times(6, i => ({ label: `Project ${i}`, installationKey: `key-${i}` })) - }); - - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(wrapper.find('Checkbox')).toHaveLength(1); - expect(wrapper.state('checkAllRepositories')).toBe(false); - expect(wrapper.state('selectedRepositories')).toEqual({}); -}); - -it('should select all repositories', async () => { - (getRepositories as jest.Mock).mockResolvedValueOnce({ - repositories: [ - { label: 'Project 1', installationKey: 'key-1' }, - { label: 'Project 2', installationKey: 'key-2', linkedProjectKey: 'key-2' } - ] - }); - - const wrapper = shallowRender(); - const instance = wrapper.instance() as RemoteRepositories; - await waitAndUpdate(wrapper); - - instance.onCheckAllRepositories(); - await waitAndUpdate(wrapper); - - expect(wrapper.state('checkAllRepositories')).toBe(true); - expect(wrapper.state('selectedRepositories')).toMatchSnapshot(); - - instance.onCheckAllRepositories(); - await waitAndUpdate(wrapper); - - expect(wrapper.state('checkAllRepositories')).toBe(false); - expect(wrapper.state('selectedRepositories')).toEqual({}); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/SetupProjectBox-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/SetupProjectBox-test.tsx deleted file mode 100644 index 6712875c47d..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/SetupProjectBox-test.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { submit, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import { provisionProject } from '../../../../api/alm-integration'; -import { mockOrganizationWithAlm } from '../../../../helpers/testMocks'; -import SetupProjectBox from '../SetupProjectBox'; - -jest.mock('../../../../api/alm-integration', () => ({ - provisionProject: jest - .fn() - .mockResolvedValue({ projects: [{ projectKey: 'awesome' }, { projectKey: 'foo' }] }) -})); - -it('should correctly create projects', async () => { - const onProjectCreate = jest.fn(); - const wrapper = shallowRender({ onProjectCreate }); - - expect(wrapper).toMatchSnapshot(); - submit(wrapper.find('form')); - expect(provisionProject).toBeCalledWith({ - installationKeys: ['github/awesome', 'github/foo'], - organization: 'foo' - }); - - await waitAndUpdate(wrapper); - expect(onProjectCreate).toBeCalledWith(['awesome', 'foo'], 'foo'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap deleted file mode 100644 index 4ac954219d5..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap +++ /dev/null @@ -1,211 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -
  • -
    -
    - - Foo Provider - - Awesome Project - -
    -
    -
  • -
    -`; - -exports[`should render disabed 1`] = ` - -
  • -
    -
    - - Foo Provider - - Awesome Project - -
    -
    -
  • -
    -`; - -exports[`should render imported 1`] = ` - -
  • -
    -
    - - Foo Provider - - Cool Project - -
    - - - - onboarding.create_project.see_project - , - } - } - /> - -
    -
  • -
    -`; - -exports[`should render private repositories 1`] = ` - -
  • -
    -
    - - Foo Provider - - Awesome Project - -
    - visibility.private -
    -
    -
    -
  • -
    -`; - -exports[`should render selected 1`] = ` - -
  • -
    -
    - - Foo Provider - - Awesome Project - -
    -
    -
  • -
    -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap deleted file mode 100644 index 2a9d628ad55..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap +++ /dev/null @@ -1,90 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should display the bound organizations dropdown with the remote repositories 1`] = ` - - - - -`; - -exports[`should display the provider app install button 1`] = ` - -

    - onboarding.create_project.install_app_description.github -

    - - onboarding.import_organization.choose_organization_button.github - -
    -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap index 7757c69cf4d..05531913bb2 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap @@ -1,73 +1,126 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render correctly for SonarCloud 1`] = ` +exports[`should render correctly 1`] = ` + - +
    + +
    `; -exports[`should render correctly for SonarQube 1`] = ` +exports[`should render correctly if no branch support 1`] = ` + - + +
    + +`; + +exports[`should render correctly if the BBS method is selected 1`] = ` + + + +
    + +
    +
    +`; + +exports[`should render correctly if the manual method is selected 1`] = ` + + + +
    + +
    `; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPageSonarCloud-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPageSonarCloud-test.tsx.snap deleted file mode 100644 index 50addeb1eab..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPageSonarCloud-test.tsx.snap +++ /dev/null @@ -1,239 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - - -
    -
    -

    - - onboarding.create_project.header - -

    -
    - -
    -
    -`; - -exports[`should render correctly 2`] = ` - - -
    -
    -

    - - onboarding.create_project.header - -

    -
    - - -
    -
    -`; - -exports[`should render with Custom creation only 1`] = ` - - -
    -
    -

    - - onboarding.create_project.header - -

    -
    - -
    -
    -`; - -exports[`should switch tabs 1`] = ` - - -
    -
    -

    - - onboarding.create_project.header - -

    -
    - - -
    -
    -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPageSonarQube-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPageSonarQube-test.tsx.snap deleted file mode 100644 index 6018c82fd3a..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPageSonarQube-test.tsx.snap +++ /dev/null @@ -1,114 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - - -
    - -
    -
    -`; - -exports[`should render correctly if no branch support 1`] = ` - - -
    - -
    -
    -`; - -exports[`should render correctly if the BBS method is selected 1`] = ` - - -
    - -
    -
    -`; - -exports[`should render correctly if the manual method is selected 1`] = ` - - -
    - -
    -
    -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap index a0189b7cfd6..baaac6282ea 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap @@ -6,7 +6,7 @@ exports[`should render correctly 1`] = ` title="onboarding.create_project.setup_manually" />
    - - - - - onboarding.create_project.create_new_org - -
    -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/RemoteRepositories-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/RemoteRepositories-test.tsx.snap deleted file mode 100644 index ffd95a3904c..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/RemoteRepositories-test.tsx.snap +++ /dev/null @@ -1,189 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should display the list of repositories 1`] = ` -
    -
    -
    -
    -
    - -
      -
    • - onboarding.create_project.no_repositories -
    • -
    -
    -
    -
    -
    - -
    -
    -
    -`; - -exports[`should display the list of repositories 2`] = ` -
    -
    -
    -
    - - onboarding.create_project.select_all_repositories - -
    -
    - -
      - - -
    -
    -
    -
    -
    - -
    -
    -
    -`; - -exports[`should display the organization upgrade box 1`] = ` - -`; - -exports[`should select all repositories 1`] = ` -Object { - "key-1": Object { - "installationKey": "key-1", - "label": "Project 1", - }, -} -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/SetupProjectBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/SetupProjectBox-test.tsx.snap deleted file mode 100644 index f91eab93477..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/SetupProjectBox-test.tsx.snap +++ /dev/null @@ -1,45 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should correctly create projects 1`] = ` -
    -
    -

    - onboarding.create_project.x_repositories_selected.2 -

    -
    -
    -
    -

    - onboarding.create_project.1_repository_created_as_public -

    -

    - onboarding.create_project.1_repository_created_as_private -

    -
    -
    - - set_up - - -
    -
    -
    -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/style.css b/server/sonar-web/src/main/js/apps/create/project/style.css index 9877a23a561..10291b37851 100644 --- a/server/sonar-web/src/main/js/apps/create/project/style.css +++ b/server/sonar-web/src/main/js/apps/create/project/style.css @@ -32,119 +32,16 @@ z-index: var(--pageMainZIndex); } -.create-project { - display: flex !important; - justify-content: space-between; -} - -.create-project-repository { - display: flex; - align-items: center; - min-width: 500px; - height: 40px; - border: 1px solid var(--barBorderColor); - padding: var(--gridSize) calc(var(--gridSize) * 2); - margin-bottom: calc(var(--gridSize)); - box-sizing: border-box; - cursor: pointer; - transition: all 0.3s ease; -} - -.create-project-repository.disabled { - background-color: var(--disableGrayBg); - border-color: var(--disableGrayBorder); - cursor: default; -} - -.create-project-repository.imported { - cursor: default; -} - -.create-project-repository.selected { - background-color: var(--lightBlue); - border-color: var(--darkBlue); -} - -.create-project-repository:not(.imported):not(.disabled):hover, -.create-project-repository:not(.imported):not(.disabled):focus, -.create-project-repository:not(.imported):not(.disabled):active { - border-color: var(--blue); - box-shadow: none; -} - -.create-project-side-with-search { - margin-top: calc(4 * var(--gridSize)); -} - -.create-project-side-sticky { - position: sticky; - top: 68px; -} - -.create-project-setup { - display: flex; - overflow: hidden; - opacity: 0; - flex-direction: column; - height: 0; - width: 450px; - margin-bottom: 0; - color: #fff; - background-color: var(--sonarcloudBlue900); - border: none; - border-radius: 3px; - transition: height 0.5s ease, opacity 0.4s ease-out, margin-bottom 0.5s ease-in; -} - -.create-project-setup.open { - opacity: 1; - height: 160px; - margin-bottom: calc(2.5 * var(--gridSize)); -} - -.create-project-setup h2 { - color: #fff; - font-weight: 700; - font-size: var(--bigFontSize); -} - -.create-project-setup .boxed-group-inner { - display: flex; - flex-direction: column; - flex-grow: 1; -} - -.create-project-setup .button { - border-color: var(--sonarcloudBlue500); - background-color: var(--sonarcloudBlue500); - color: #fff; - transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; -} - -.create-project-setup .button:hover, -.create-project-setup .button:focus { - border-color: var(--sonarcloudBlue600); - background-color: var(--sonarcloudBlue600); -} - -.create-project-actions { - min-width: 500px; - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 0 8px 16px; - border-left: 1px solid transparent; -} - -.create-project-actions .icon-checkbox { - margin-right: 8px; -} - .create-project-modes { margin: 0 auto; max-width: 500px; } +.create-project-manual { + display: flex !important; + justify-content: space-between; +} + .create-project-import-bbs .open .boxed-group-header { border-bottom: 1px solid var(--barBorderColor); }