aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>2022-11-17 15:59:16 +0100
committersonartech <sonartech@sonarsource.com>2022-11-22 20:03:04 +0000
commit9d2a38de3347dc85890fae454f82154a52267a69 (patch)
treec113ef64cea2bfe1f2f2b0734643faf7abc45f3a /server/sonar-web
parent4d779c10b3e45cb2ea734af9cfa235690f68916a (diff)
downloadsonarqube-9d2a38de3347dc85890fae454f82154a52267a69.tar.gz
sonarqube-9d2a38de3347dc85890fae454f82154a52267a69.zip
SONAR-17588 Allow project onboarding when multiple Bitbucket integrations are configured
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx33
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx46
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx21
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx51
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx20
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx55
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap13
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap62
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap40
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap107
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap152
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/constants.ts4
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx15
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx21
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap42
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap10
-rw-r--r--server/sonar-web/src/main/js/types/alm-settings.ts7
27 files changed, 539 insertions, 224 deletions
diff --git a/server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx b/server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx
index 1bd3d726f48..6a6776fb355 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx
@@ -28,24 +28,25 @@ export interface AlmSettingsInstanceDropdownProps {
onChangeConfig: (instance: AlmSettingsInstance) => void;
}
+const MIN_SIZE_INSTANCES = 2;
+
export default function AlmSettingsInstanceDropdown(props: AlmSettingsInstanceDropdownProps) {
const { almInstances, selectedAlmInstance } = props;
+ if (!almInstances || almInstances.length < MIN_SIZE_INSTANCES) {
+ return null;
+ }
return (
- <>
- {almInstances && almInstances.length > 1 ? (
- <div className="display-flex-column huge-spacer-bottom">
- <label htmlFor="alm-config-selector" className="spacer-bottom">
- {translate('alm.configuration.selector.label')}
- </label>
- <AlmSettingsInstanceSelector
- instances={almInstances}
- onChange={props.onChangeConfig}
- initialValue={selectedAlmInstance ? selectedAlmInstance.key : undefined}
- classNames="abs-width-400"
- inputId="alm-config-selector"
- />
- </div>
- ) : null}
- </>
+ <div className="display-flex-column huge-spacer-bottom">
+ <label htmlFor="alm-config-selector" className="spacer-bottom">
+ {translate('alm.configuration.selector.label')}
+ </label>
+ <AlmSettingsInstanceSelector
+ instances={almInstances}
+ onChange={props.onChangeConfig}
+ initialValue={selectedAlmInstance ? selectedAlmInstance.key : undefined}
+ classNames="abs-width-400"
+ inputId="alm-config-selector"
+ />
+ </div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx
index a091375ccad..0ee1f087eb4 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx
@@ -30,7 +30,7 @@ import BitbucketCloudProjectCreateRenderer from './BitbucketCloudProjectCreateRe
interface Props {
canAdmin: boolean;
- settings: AlmSettingsInstance[];
+ almInstances: AlmSettingsInstance[];
loadingBindings: boolean;
onProjectCreate: (projectKey: string) => void;
location: Location;
@@ -47,7 +47,7 @@ interface State {
repositories: BitbucketCloudRepository[];
searching: boolean;
searchQuery: string;
- settings: AlmSettingsInstance;
+ selectedAlmInstance: AlmSettingsInstance;
showPersonalAccessTokenForm: boolean;
}
@@ -67,7 +67,7 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
repositories: [],
searching: false,
searchQuery: '',
- settings: props.settings[0],
+ selectedAlmInstance: props.almInstances[0],
showPersonalAccessTokenForm: true,
};
}
@@ -77,8 +77,8 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
}
componentDidUpdate(prevProps: Props) {
- if (prevProps.settings.length === 0 && this.props.settings.length > 0) {
- this.setState({ settings: this.props.settings[0] }, () => this.fetchData());
+ if (prevProps.almInstances.length === 0 && this.props.almInstances.length > 0) {
+ this.setState({ selectedAlmInstance: this.props.almInstances[0] }, () => this.fetchData());
}
}
@@ -98,14 +98,14 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
async fetchData(more = false) {
const {
- settings,
+ selectedAlmInstance,
searchQuery,
projectsPaging: { pageIndex, pageSize },
showPersonalAccessTokenForm,
} = this.state;
- if (settings && !showPersonalAccessTokenForm) {
+ if (selectedAlmInstance && !showPersonalAccessTokenForm) {
const { isLastPage, repositories } = await searchForBitbucketCloudRepositories(
- settings.key,
+ selectedAlmInstance.key,
searchQuery,
pageSize,
pageIndex
@@ -174,17 +174,18 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
};
handleImport = async (repositorySlug: string) => {
- const { settings } = this.state;
+ const { selectedAlmInstance } = this.state;
- if (!settings) {
+ if (!selectedAlmInstance) {
return;
}
this.setState({ importingSlug: repositorySlug });
- const result = await importBitbucketCloudRepository(settings.key, repositorySlug).catch(
- () => undefined
- );
+ const result = await importBitbucketCloudRepository(
+ selectedAlmInstance.key,
+ repositorySlug
+ ).catch(() => undefined);
if (this.mounted) {
this.setState({ importingSlug: undefined });
@@ -195,12 +196,23 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
}
};
+ onSelectedAlmInstanceChange = (instance: AlmSettingsInstance) => {
+ this.setState({
+ selectedAlmInstance: instance,
+ showPersonalAccessTokenForm: true,
+ resetPat: false,
+ searching: false,
+ searchQuery: '',
+ projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE },
+ });
+ };
+
render() {
- const { canAdmin, loadingBindings, location } = this.props;
+ const { canAdmin, loadingBindings, location, almInstances } = this.props;
const {
importingSlug,
isLastPage = true,
- settings,
+ selectedAlmInstance,
loading,
loadingMore,
repositories,
@@ -213,7 +225,8 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
<BitbucketCloudProjectCreateRenderer
importingSlug={importingSlug}
isLastPage={isLastPage}
- settings={settings}
+ selectedAlmInstance={selectedAlmInstance}
+ almInstances={almInstances}
canAdmin={canAdmin}
loadingMore={loadingMore}
loading={loading || loadingBindings}
@@ -221,6 +234,7 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
onLoadMore={this.handleLoadMore}
onPersonalAccessTokenCreated={this.handlePersonalAccessTokenCreated}
onSearch={this.handleSearch}
+ onSelectedAlmInstanceChange={this.onSelectedAlmInstanceChange}
repositories={repositories}
searching={searching}
searchQuery={searchQuery}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx
index 359b1e65014..514a8db6df6 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx
@@ -22,6 +22,7 @@ import { translate } from '../../../helpers/l10n';
import { getBaseUrl } from '../../../helpers/system';
import { BitbucketCloudRepository } from '../../../types/alm-integration';
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
+import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown';
import BitbucketCloudSearchForm from './BitbucketCloudSearchForm';
import CreateProjectPageHeader from './CreateProjectPageHeader';
import PersonalAccessTokenForm from './PersonalAccessTokenForm';
@@ -37,21 +38,24 @@ export interface BitbucketCloudProjectCreateRendererProps {
onLoadMore: () => void;
onPersonalAccessTokenCreated: () => void;
onSearch: (searchQuery: string) => void;
+ onSelectedAlmInstanceChange: (instance: AlmSettingsInstance) => void;
repositories?: BitbucketCloudRepository[];
resetPat: boolean;
searching: boolean;
searchQuery: string;
showPersonalAccessTokenForm: boolean;
- settings?: AlmSettingsInstance;
+ almInstances: AlmSettingsInstance[];
+ selectedAlmInstance?: AlmSettingsInstance;
}
export default function BitbucketCloudProjectCreateRenderer(
props: BitbucketCloudProjectCreateRendererProps
) {
const {
+ almInstances,
importingSlug,
isLastPage,
- settings,
+ selectedAlmInstance,
canAdmin,
loading,
loadingMore,
@@ -77,17 +81,24 @@ export default function BitbucketCloudProjectCreateRenderer(
</span>
}
/>
+
+ <AlmSettingsInstanceDropdown
+ almInstances={almInstances}
+ selectedAlmInstance={selectedAlmInstance}
+ onChangeConfig={props.onSelectedAlmInstanceChange}
+ />
+
{loading && <i className="spinner" />}
- {!loading && !settings && (
+ {!loading && !selectedAlmInstance && (
<WrongBindingCountAlert alm={AlmKeys.BitbucketCloud} canAdmin={!!canAdmin} />
)}
{!loading &&
- settings &&
+ selectedAlmInstance &&
(showPersonalAccessTokenForm ? (
<PersonalAccessTokenForm
- almSetting={settings}
+ almSetting={selectedAlmInstance}
resetPat={resetPat}
onPersonalAccessTokenCreated={props.onPersonalAccessTokenCreated}
/>
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx
index 97b08aeed0d..92ad18e876b 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx
@@ -36,7 +36,7 @@ import { DEFAULT_BBS_PAGE_SIZE } from './constants';
interface Props {
canAdmin: boolean;
- bitbucketSettings: AlmSettingsInstance[];
+ almInstances: AlmSettingsInstance[];
loadingBindings: boolean;
onProjectCreate: (projectKey: string) => void;
location: Location;
@@ -44,7 +44,7 @@ interface Props {
}
interface State {
- bitbucketSetting?: AlmSettingsInstance;
+ selectedAlmInstance?: AlmSettingsInstance;
importing: boolean;
loading: boolean;
projects?: BitbucketProject[];
@@ -63,7 +63,7 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
this.state = {
// For now, we only handle a single instance. So we always use the first
// one from the list.
- bitbucketSetting: props.bitbucketSettings[0],
+ selectedAlmInstance: props.almInstances[0],
importing: false,
loading: false,
searching: false,
@@ -76,8 +76,8 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
}
componentDidUpdate(prevProps: Props) {
- if (prevProps.bitbucketSettings.length === 0 && this.props.bitbucketSettings.length > 0) {
- this.setState({ bitbucketSetting: this.props.bitbucketSettings[0] }, () =>
+ if (prevProps.almInstances.length === 0 && this.props.almInstances.length > 0) {
+ this.setState({ selectedAlmInstance: this.props.almInstances[0] }, () =>
this.fetchInitialData()
);
}
@@ -112,27 +112,27 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
};
fetchBitbucketProjects = (): Promise<BitbucketProject[] | undefined> => {
- const { bitbucketSetting } = this.state;
+ const { selectedAlmInstance } = this.state;
- if (!bitbucketSetting) {
+ if (!selectedAlmInstance) {
return Promise.resolve(undefined);
}
- return getBitbucketServerProjects(bitbucketSetting.key).then(({ projects }) => projects);
+ return getBitbucketServerProjects(selectedAlmInstance.key).then(({ projects }) => projects);
};
fetchBitbucketRepositories = (
projects: BitbucketProject[]
): Promise<BitbucketProjectRepositories | undefined> => {
- const { bitbucketSetting } = this.state;
+ const { selectedAlmInstance } = this.state;
- if (!bitbucketSetting) {
+ if (!selectedAlmInstance) {
return Promise.resolve(undefined);
}
return Promise.all(
projects.map((p) => {
- return getBitbucketServerRepositories(bitbucketSetting.key, p.name).then(
+ return getBitbucketServerRepositories(selectedAlmInstance.key, p.name).then(
({ isLastPage, repositories }) => {
// Because the WS uses the project name rather than its key to find
// repositories, we can match more repositories than we expect. For
@@ -183,15 +183,15 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
};
handleImportRepository = () => {
- const { bitbucketSetting, selectedRepository } = this.state;
+ const { selectedAlmInstance, selectedRepository } = this.state;
- if (!bitbucketSetting || !selectedRepository) {
+ if (!selectedAlmInstance || !selectedRepository) {
return;
}
this.setState({ importing: true });
importBitbucketServerProject(
- bitbucketSetting.key,
+ selectedAlmInstance.key,
selectedRepository.projectKey,
selectedRepository.slug
)
@@ -209,9 +209,9 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
};
handleSearch = (query: string) => {
- const { bitbucketSetting } = this.state;
+ const { selectedAlmInstance } = this.state;
- if (!bitbucketSetting) {
+ if (!selectedAlmInstance) {
return;
}
@@ -221,7 +221,7 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
}
this.setState({ searching: true, selectedRepository: undefined });
- searchForBitbucketServerRepositories(bitbucketSetting.key, query)
+ searchForBitbucketServerRepositories(selectedAlmInstance.key, query)
.then(({ repositories }) => {
if (this.mounted) {
this.setState({ searching: false, searchResults: repositories });
@@ -238,10 +238,19 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
this.setState({ selectedRepository });
};
+ onSelectedAlmInstanceChange = (instance: AlmSettingsInstance) => {
+ this.setState({
+ selectedAlmInstance: instance,
+ showPersonalAccessTokenForm: true,
+ searching: false,
+ searchResults: undefined,
+ });
+ };
+
render() {
- const { canAdmin, loadingBindings, location } = this.props;
+ const { canAdmin, loadingBindings, location, almInstances } = this.props;
const {
- bitbucketSetting,
+ selectedAlmInstance,
importing,
loading,
projectRepositories,
@@ -254,7 +263,8 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
return (
<BitbucketCreateProjectRenderer
- bitbucketSetting={bitbucketSetting}
+ selectedAlmInstance={selectedAlmInstance}
+ almInstances={almInstances}
canAdmin={canAdmin}
importing={importing}
loading={loading || loadingBindings}
@@ -262,6 +272,7 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
onPersonalAccessTokenCreated={this.handlePersonalAccessTokenCreated}
onSearch={this.handleSearch}
onSelectRepository={this.handleSelectRepository}
+ onSelectedAlmInstanceChange={this.onSelectedAlmInstanceChange}
projectRepositories={projectRepositories}
projects={projects}
resetPat={Boolean(location.query.resetPat)}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx
index 4c001740ea6..4a0f98f84ba 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx
@@ -28,13 +28,15 @@ import {
BitbucketRepository,
} from '../../../types/alm-integration';
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
+import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown';
import BitbucketImportRepositoryForm from './BitbucketImportRepositoryForm';
import CreateProjectPageHeader from './CreateProjectPageHeader';
import PersonalAccessTokenForm from './PersonalAccessTokenForm';
import WrongBindingCountAlert from './WrongBindingCountAlert';
export interface BitbucketProjectCreateRendererProps {
- bitbucketSetting?: AlmSettingsInstance;
+ selectedAlmInstance?: AlmSettingsInstance;
+ almInstances: AlmSettingsInstance[];
canAdmin?: boolean;
importing: boolean;
loading: boolean;
@@ -42,6 +44,7 @@ export interface BitbucketProjectCreateRendererProps {
onSearch: (query: string) => void;
onSelectRepository: (repo: BitbucketRepository) => void;
onPersonalAccessTokenCreated: () => void;
+ onSelectedAlmInstanceChange: (instance: AlmSettingsInstance) => void;
projects?: BitbucketProject[];
projectRepositories?: BitbucketProjectRepositories;
resetPat: boolean;
@@ -53,7 +56,8 @@ export interface BitbucketProjectCreateRendererProps {
export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCreateRendererProps) {
const {
- bitbucketSetting,
+ almInstances,
+ selectedAlmInstance,
canAdmin,
importing,
loading,
@@ -96,17 +100,23 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={almInstances}
+ selectedAlmInstance={selectedAlmInstance}
+ onChangeConfig={props.onSelectedAlmInstanceChange}
+ />
+
{loading && <i className="spinner" />}
- {!loading && !bitbucketSetting && (
+ {!loading && !selectedAlmInstance && (
<WrongBindingCountAlert alm={AlmKeys.BitbucketServer} canAdmin={!!canAdmin} />
)}
{!loading &&
- bitbucketSetting &&
+ selectedAlmInstance &&
(showPersonalAccessTokenForm ? (
<PersonalAccessTokenForm
- almSetting={bitbucketSetting}
+ almSetting={selectedAlmInstance}
onPersonalAccessTokenCreated={props.onPersonalAccessTokenCreated}
resetPat={resetPat}
/>
diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx
index 22f27994a94..ac16e767c1d 100644
--- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx
@@ -24,11 +24,10 @@ import classNames from 'classnames';
import * as React from 'react';
import withAppStateContext from '../../../app/components/app-state/withAppStateContext';
import ChevronsIcon from '../../../components/icons/ChevronsIcon';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
import { getBaseUrl } from '../../../helpers/system';
-import { AlmKeys } from '../../../types/alm-settings';
+import { AlmKeys, AlmKeysUnion } from '../../../types/alm-settings';
import { AppState } from '../../../types/appstate';
-import { ALLOWED_MULTIPLE_CONFIGS } from './constants';
import { CreateProjectModes } from './types';
export interface CreateProjectModeSelectionProps {
@@ -43,35 +42,18 @@ export interface CreateProjectModeSelectionProps {
const DEFAULT_ICON_SIZE = 50;
-function getErrorMessage(
- hasTooManyConfig: boolean,
- hasConfig: boolean,
- canAdmin: boolean | undefined,
- alm: AlmKeys
-) {
- if (hasTooManyConfig) {
- return translateWithParameters(
- 'onboarding.create_project.too_many_alm_instances_X',
- translate('alm', alm)
- );
- } else if (!hasConfig) {
+function getErrorMessage(hasConfig: boolean, canAdmin: boolean | undefined) {
+ if (!hasConfig) {
return canAdmin
? translate('onboarding.create_project.alm_not_configured.admin')
: translate('onboarding.create_project.alm_not_configured');
}
-}
-
-function getMode(
- isBitbucketOption: boolean,
- hasBitbucketCloudConf: boolean,
- mode: CreateProjectModes
-) {
- return isBitbucketOption && hasBitbucketCloudConf ? CreateProjectModes.BitbucketCloud : mode;
+ return undefined;
}
function renderAlmOption(
props: CreateProjectModeSelectionProps,
- alm: AlmKeys.Azure | AlmKeys.BitbucketServer | AlmKeys.GitHub | AlmKeys.GitLab,
+ alm: AlmKeysUnion,
mode: CreateProjectModes,
last = false
) {
@@ -80,30 +62,26 @@ function renderAlmOption(
appState: { canAdmin },
loadingBindings,
} = props;
-
- const hasBitbucketCloudConf = almCounts[AlmKeys.BitbucketCloud] > 0;
- const isBitbucketOption = alm === AlmKeys.BitbucketServer;
-
- const count = isBitbucketOption
- ? almCounts[AlmKeys.BitbucketServer] + almCounts[AlmKeys.BitbucketCloud]
- : almCounts[alm];
+ const count = almCounts[alm];
const hasConfig = count > 0;
- const hasTooManyConfig = count > 1 && !ALLOWED_MULTIPLE_CONFIGS.includes(alm);
- const disabled = loadingBindings || hasTooManyConfig || (!hasConfig && !canAdmin);
+ const disabled = loadingBindings || (!hasConfig && !canAdmin);
const onClick = () => {
- if (hasTooManyConfig || (!hasConfig && !canAdmin)) {
+ if (!hasConfig && !canAdmin) {
return null;
}
if (!hasConfig && canAdmin) {
- return props.onConfigMode(alm);
+ const configMode = alm === AlmKeys.BitbucketCloud ? AlmKeys.BitbucketServer : alm;
+ return props.onConfigMode(configMode);
}
- return props.onSelectMode(getMode(isBitbucketOption, hasBitbucketCloudConf, mode));
+ return props.onSelectMode(mode);
};
- const errorMessage = getErrorMessage(hasTooManyConfig, hasConfig, canAdmin, alm);
+ const errorMessage = getErrorMessage(hasConfig, canAdmin);
+
+ const svgFileName = alm === AlmKeys.BitbucketCloud ? AlmKeys.BitbucketServer : alm;
return (
<div className="display-flex-column">
@@ -119,7 +97,7 @@ function renderAlmOption(
<img
alt="" // Should be ignored by screen readers
height={DEFAULT_ICON_SIZE}
- src={`${getBaseUrl()}/images/alm/${alm}.svg`}
+ src={`${getBaseUrl()}/images/alm/${svgFileName}.svg`}
/>
<div className="medium big-spacer-top abs-height-50 display-flex-center">
{translate('onboarding.create_project.select_method', alm)}
@@ -164,6 +142,7 @@ export function CreateProjectModeSelection(props: CreateProjectModeSelectionProp
<div className="big-spacer-top huge-spacer-bottom display-flex-center">
{renderAlmOption(props, AlmKeys.Azure, CreateProjectModes.AzureDevOps)}
{renderAlmOption(props, AlmKeys.BitbucketServer, CreateProjectModes.BitbucketServer)}
+ {renderAlmOption(props, AlmKeys.BitbucketCloud, CreateProjectModes.BitbucketCloud)}
{renderAlmOption(props, AlmKeys.GitHub, CreateProjectModes.GitHub)}
{renderAlmOption(props, AlmKeys.GitLab, CreateProjectModes.GitLab, true)}
</div>
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 aa6f2ff06b6..34660ee0bb8 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
@@ -179,7 +179,7 @@ export class CreateProjectPage extends React.PureComponent<CreateProjectPageProp
return (
<BitbucketProjectCreate
canAdmin={!!canAdmin}
- bitbucketSettings={bitbucketSettings}
+ almInstances={bitbucketSettings}
loadingBindings={loading}
location={location}
onProjectCreate={this.handleProjectCreate}
@@ -195,7 +195,7 @@ export class CreateProjectPage extends React.PureComponent<CreateProjectPageProp
location={location}
onProjectCreate={this.handleProjectCreate}
router={router}
- settings={bitbucketCloudSettings}
+ almInstances={bitbucketCloudSettings}
/>
);
}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx
index 7d2263cc0b4..4aee42212ca 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx
@@ -46,10 +46,10 @@ jest.mock('../../../../api/alm-integrations', () => {
});
it('Should render correctly', async () => {
- const wrapper = shallowRender({ settings: [] });
+ const wrapper = shallowRender({ almInstances: [] });
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
- wrapper.setProps({ settings: [mockBitbucketCloudAlmSettingsInstance()] });
+ wrapper.setProps({ almInstances: [mockBitbucketCloudAlmSettingsInstance()] });
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot('Setting changeds');
});
@@ -174,7 +174,7 @@ function shallowRender(props?: Partial<BitbucketCloudProjectCreate['props']>) {
location={mockLocation()}
canAdmin={true}
router={mockRouter()}
- settings={[mockBitbucketCloudAlmSettingsInstance()]}
+ almInstances={[mockBitbucketCloudAlmSettingsInstance()]}
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx
index 951aa97fbd1..43c4f5c6b80 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx
@@ -26,7 +26,7 @@ import BitbucketCloudProjectCreateRenderer, {
it('Should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
- expect(shallowRender({ settings: undefined })).toMatchSnapshot('Wrong config');
+ expect(shallowRender({ selectedAlmInstance: undefined })).toMatchSnapshot('Wrong config');
expect(shallowRender({ loading: true })).toMatchSnapshot('Loading...');
expect(
shallowRender({
@@ -48,7 +48,9 @@ function shallowRender(props?: Partial<BitbucketCloudProjectCreateRendererProps>
resetPat={false}
searching={false}
searchQuery=""
- settings={mockBitbucketCloudAlmSettingsInstance()}
+ selectedAlmInstance={mockBitbucketCloudAlmSettingsInstance()}
+ almInstances={[mockBitbucketCloudAlmSettingsInstance()]}
+ onSelectedAlmInstanceChange={jest.fn()}
showPersonalAccessTokenForm={false}
{...props}
/>
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx
index c4d108190ca..91a6ea85605 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx
@@ -66,7 +66,7 @@ beforeEach(jest.clearAllMocks);
it('should render correctly', async () => {
expect(shallowRender()).toMatchSnapshot();
- expect(shallowRender({ bitbucketSettings: [] })).toMatchSnapshot('No setting');
+ expect(shallowRender({ almInstances: [] })).toMatchSnapshot('No setting');
const wrapper = shallowRender();
(getBitbucketServerRepositories as jest.Mock).mockRejectedValueOnce({});
@@ -130,7 +130,7 @@ it('should correctly handle search', async () => {
});
it('should behave correctly when no setting', async () => {
- const wrapper = shallowRender({ bitbucketSettings: [] });
+ const wrapper = shallowRender({ almInstances: [] });
await wrapper.instance().handleSearch('');
await wrapper.instance().handleImportRepository();
await wrapper.instance().fetchBitbucketRepositories([mockBitbucketProject()]);
@@ -144,7 +144,7 @@ function shallowRender(props: Partial<BitbucketProjectCreate['props']> = {}) {
return shallow<BitbucketProjectCreate>(
<BitbucketProjectCreate
canAdmin={false}
- bitbucketSettings={[mockAlmSettingsInstance({ alm: AlmKeys.BitbucketServer, key: 'foo' })]}
+ almInstances={[mockAlmSettingsInstance({ alm: AlmKeys.BitbucketServer, key: 'foo' })]}
loadingBindings={false}
location={mockLocation()}
router={mockRouter()}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx
index d771028e1df..41dc80e94e2 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx
@@ -37,10 +37,10 @@ it('should render correctly', () => {
expect(shallowRender({ selectedRepository: mockBitbucketRepository() })).toMatchSnapshot(
'selected repo'
);
- expect(shallowRender({ bitbucketSetting: undefined })).toMatchSnapshot(
+ expect(shallowRender({ selectedAlmInstance: undefined })).toMatchSnapshot(
'invalid config, regular user'
);
- expect(shallowRender({ bitbucketSetting: undefined, canAdmin: true })).toMatchSnapshot(
+ expect(shallowRender({ selectedAlmInstance: undefined, canAdmin: true })).toMatchSnapshot(
'invalid config, admin user'
);
});
@@ -48,7 +48,9 @@ it('should render correctly', () => {
function shallowRender(props: Partial<BitbucketProjectCreateRendererProps> = {}) {
return shallow<BitbucketProjectCreateRendererProps>(
<BitbucketProjectCreateRenderer
- bitbucketSetting={mockAlmSettingsInstance({ alm: AlmKeys.BitbucketServer })}
+ selectedAlmInstance={mockAlmSettingsInstance({ alm: AlmKeys.BitbucketServer })}
+ almInstances={[mockAlmSettingsInstance({ alm: AlmKeys.BitbucketServer })]}
+ onSelectedAlmInstanceChange={jest.fn()}
importing={false}
loading={false}
onImportRepository={jest.fn()}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx
index 0301387ae44..e677e2a580d 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx
@@ -79,10 +79,14 @@ it('should correctly pass the selected mode up', () => {
onSelectMode.mockClear();
click(wrapper.find(almButton).at(2));
- expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.GitHub);
+ expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.BitbucketCloud);
onSelectMode.mockClear();
click(wrapper.find(almButton).at(3));
+ expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.GitHub);
+ onSelectMode.mockClear();
+
+ click(wrapper.find(almButton).at(4));
expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.GitLab);
onSelectMode.mockClear();
@@ -91,7 +95,7 @@ it('should correctly pass the selected mode up', () => {
{ [AlmKeys.BitbucketCloud]: 1, [AlmKeys.BitbucketServer]: 0 }
);
- click(wrapper.find(almButton).at(1));
+ click(wrapper.find(almButton).at(2));
expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.BitbucketCloud);
onSelectMode.mockClear();
});
@@ -136,7 +140,7 @@ function shallowRender(
) {
const almCounts = {
[AlmKeys.Azure]: 1,
- [AlmKeys.BitbucketCloud]: 0,
+ [AlmKeys.BitbucketCloud]: 1,
[AlmKeys.BitbucketServer]: 1,
[AlmKeys.GitHub]: 1,
[AlmKeys.GitLab]: 1,
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap
index 8861fde1541..efaf694bc72 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap
@@ -2,6 +2,7 @@
exports[`Should render correctly 1`] = `
<BitbucketCloudProjectCreateRenderer
+ almInstances={Array []}
canAdmin={true}
isLastPage={true}
loading={false}
@@ -10,6 +11,7 @@ exports[`Should render correctly 1`] = `
onLoadMore={[Function]}
onPersonalAccessTokenCreated={[Function]}
onSearch={[Function]}
+ onSelectedAlmInstanceChange={[Function]}
repositories={Array []}
resetPat={false}
searchQuery=""
@@ -20,6 +22,14 @@ exports[`Should render correctly 1`] = `
exports[`Should render correctly: Setting changeds 1`] = `
<BitbucketCloudProjectCreateRenderer
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ },
+ ]
+ }
canAdmin={true}
isLastPage={true}
loading={false}
@@ -28,11 +38,12 @@ exports[`Should render correctly: Setting changeds 1`] = `
onLoadMore={[Function]}
onPersonalAccessTokenCreated={[Function]}
onSearch={[Function]}
+ onSelectedAlmInstanceChange={[Function]}
repositories={Array []}
resetPat={false}
searchQuery=""
searching={false}
- settings={
+ selectedAlmInstance={
Object {
"alm": "bitbucketcloud",
"key": "key",
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap
index eb413b12cc6..ef927ced83a 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap
@@ -17,6 +17,23 @@ exports[`Should render correctly 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ }
+ }
+ />
<BitbucketCloudSearchForm
isLastPage={true}
loadingMore={false}
@@ -46,6 +63,23 @@ exports[`Should render correctly: Loading... 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ }
+ }
+ />
<i
className="spinner"
/>
@@ -69,6 +103,23 @@ exports[`Should render correctly: Need App password 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ }
+ }
+ />
<PersonalAccessTokenForm
almSetting={
Object {
@@ -99,6 +150,17 @@ exports[`Should render correctly: Wrong config 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucketcloud",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ />
<WrongBindingCountAlert
alm="bitbucketcloud"
canAdmin={false}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap
index c06e0b818bf..e168e70e45b 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap
@@ -2,11 +2,13 @@
exports[`should render correctly 1`] = `
<BitbucketProjectCreateRenderer
- bitbucketSetting={
- Object {
- "alm": "bitbucket",
- "key": "foo",
- }
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ },
+ ]
}
canAdmin={false}
importing={false}
@@ -15,19 +17,28 @@ exports[`should render correctly 1`] = `
onPersonalAccessTokenCreated={[Function]}
onSearch={[Function]}
onSelectRepository={[Function]}
+ onSelectedAlmInstanceChange={[Function]}
resetPat={false}
searching={false}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ }
+ }
showPersonalAccessTokenForm={true}
/>
`;
exports[`should render correctly: No repository 1`] = `
<BitbucketProjectCreateRenderer
- bitbucketSetting={
- Object {
- "alm": "bitbucket",
- "key": "foo",
- }
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ },
+ ]
}
canAdmin={false}
importing={false}
@@ -36,6 +47,7 @@ exports[`should render correctly: No repository 1`] = `
onPersonalAccessTokenCreated={[Function]}
onSearch={[Function]}
onSelectRepository={[Function]}
+ onSelectedAlmInstanceChange={[Function]}
projects={
Array [
Object {
@@ -52,12 +64,19 @@ exports[`should render correctly: No repository 1`] = `
}
resetPat={false}
searching={false}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ }
+ }
showPersonalAccessTokenForm={false}
/>
`;
exports[`should render correctly: No setting 1`] = `
<BitbucketProjectCreateRenderer
+ almInstances={Array []}
canAdmin={false}
importing={false}
loading={false}
@@ -65,6 +84,7 @@ exports[`should render correctly: No setting 1`] = `
onPersonalAccessTokenCreated={[Function]}
onSearch={[Function]}
onSelectRepository={[Function]}
+ onSelectedAlmInstanceChange={[Function]}
resetPat={false}
searching={false}
showPersonalAccessTokenForm={true}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap
index c499c0accea..b9f83f3dd5c 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap
@@ -34,6 +34,23 @@ exports[`should render correctly: default 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ }
+ }
+ />
<BitbucketImportRepositoryForm
disableRepositories={false}
onSearch={[MockFunction]}
@@ -101,6 +118,23 @@ exports[`should render correctly: importing 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ }
+ }
+ />
<BitbucketImportRepositoryForm
disableRepositories={true}
onSearch={[MockFunction]}
@@ -168,6 +202,17 @@ exports[`should render correctly: invalid config, admin user 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ />
<WrongBindingCountAlert
alm="bitbucket"
canAdmin={true}
@@ -209,6 +254,17 @@ exports[`should render correctly: invalid config, regular user 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ />
<WrongBindingCountAlert
alm="bitbucket"
canAdmin={false}
@@ -250,6 +306,23 @@ exports[`should render correctly: loading 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ }
+ }
+ />
<i
className="spinner"
/>
@@ -274,6 +347,23 @@ exports[`should render correctly: pat form 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ }
+ }
+ />
<PersonalAccessTokenForm
almSetting={
Object {
@@ -321,6 +411,23 @@ exports[`should render correctly: selected repo 1`] = `
</span>
}
/>
+ <AlmSettingsInstanceDropdown
+ almInstances={
+ Array [
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ },
+ ]
+ }
+ onChangeConfig={[MockFunction]}
+ selectedAlmInstance={
+ Object {
+ "alm": "bitbucket",
+ "key": "key",
+ }
+ }
+ />
<BitbucketImportRepositoryForm
disableRepositories={false}
onSearch={[MockFunction]}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap
index 2d6c27f9ac7..36a8a852f6b 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap
@@ -67,6 +67,27 @@ exports[`should render correctly: default 1`] = `
<img
alt=""
height={50}
+ src="/images/alm/bitbucket.svg"
+ />
+ <div
+ className="medium big-spacer-top abs-height-50 display-flex-center"
+ >
+ onboarding.create_project.select_method.bitbucketcloud
+ </div>
+ </button>
+ </div>
+ <div
+ className="display-flex-column"
+ >
+ <button
+ className="button button-huge display-flex-column create-project-mode-type-alm big-spacer-right"
+ disabled={false}
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={50}
src="/images/alm/github.svg"
/>
<div
@@ -197,6 +218,27 @@ exports[`should render correctly: invalid configs, admin 1`] = `
<img
alt=""
height={50}
+ src="/images/alm/bitbucket.svg"
+ />
+ <div
+ className="medium big-spacer-top abs-height-50 display-flex-center"
+ >
+ onboarding.create_project.select_method.bitbucketcloud
+ </div>
+ </button>
+ </div>
+ <div
+ className="display-flex-column"
+ >
+ <button
+ className="button button-huge display-flex-column create-project-mode-type-alm big-spacer-right"
+ disabled={false}
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={50}
src="/images/alm/github.svg"
/>
<div
@@ -327,6 +369,37 @@ exports[`should render correctly: invalid configs, admin 2`] = `
<img
alt=""
height={50}
+ src="/images/alm/bitbucket.svg"
+ />
+ <div
+ className="medium big-spacer-top abs-height-50 display-flex-center"
+ >
+ onboarding.create_project.select_method.bitbucketcloud
+ </div>
+ <p
+ className="text-muted small spacer-top"
+ style={
+ Object {
+ "lineHeight": 1.5,
+ }
+ }
+ >
+ onboarding.create_project.alm_not_configured.admin
+ </p>
+ </button>
+ </div>
+ <div
+ className="display-flex-column"
+ >
+ <button
+ className="button button-huge display-flex-column create-project-mode-type-alm big-spacer-right"
+ disabled={false}
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={50}
src="/images/alm/github.svg"
/>
<div
@@ -457,6 +530,27 @@ exports[`should render correctly: invalid configs, not admin 1`] = `
<img
alt=""
height={50}
+ src="/images/alm/bitbucket.svg"
+ />
+ <div
+ className="medium big-spacer-top abs-height-50 display-flex-center"
+ >
+ onboarding.create_project.select_method.bitbucketcloud
+ </div>
+ </button>
+ </div>
+ <div
+ className="display-flex-column"
+ >
+ <button
+ className="button button-huge display-flex-column create-project-mode-type-alm big-spacer-right"
+ disabled={false}
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={50}
src="/images/alm/github.svg"
/>
<div
@@ -589,6 +683,33 @@ exports[`should render correctly: loading instances 1`] = `
<img
alt=""
height={50}
+ src="/images/alm/bitbucket.svg"
+ />
+ <div
+ className="medium big-spacer-top abs-height-50 display-flex-center"
+ >
+ onboarding.create_project.select_method.bitbucketcloud
+ </div>
+ <span>
+ onboarding.create_project.check_alm_supported
+ <i
+ className="little-spacer-left spinner"
+ />
+ </span>
+ </button>
+ </div>
+ <div
+ className="display-flex-column"
+ >
+ <button
+ className="button button-huge display-flex-column create-project-mode-type-alm disabled big-spacer-right"
+ disabled={true}
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={50}
src="/images/alm/github.svg"
/>
<div
@@ -746,6 +867,37 @@ exports[`should render correctly: no alm conf yet, admin 1`] = `
<img
alt=""
height={50}
+ src="/images/alm/bitbucket.svg"
+ />
+ <div
+ className="medium big-spacer-top abs-height-50 display-flex-center"
+ >
+ onboarding.create_project.select_method.bitbucketcloud
+ </div>
+ <p
+ className="text-muted small spacer-top"
+ style={
+ Object {
+ "lineHeight": 1.5,
+ }
+ }
+ >
+ onboarding.create_project.alm_not_configured.admin
+ </p>
+ </button>
+ </div>
+ <div
+ className="display-flex-column"
+ >
+ <button
+ className="button button-huge display-flex-column create-project-mode-type-alm big-spacer-right"
+ disabled={false}
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={50}
src="/images/alm/github.svg"
/>
<div
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 623e4d2b0dc..6ec13628e53 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
@@ -143,7 +143,7 @@ exports[`should render correctly for bitbucket mode 1`] = `
id="create-project"
>
<BitbucketProjectCreate
- bitbucketSettings={Array []}
+ almInstances={Array []}
canAdmin={false}
loadingBindings={true}
location={
@@ -194,6 +194,7 @@ exports[`should render correctly for bitbucketcloud mode 1`] = `
id="create-project"
>
<BitbucketCloudProjectCreate
+ almInstances={Array []}
canAdmin={false}
loadingBindings={true}
location={
@@ -222,7 +223,6 @@ exports[`should render correctly for bitbucketcloud mode 1`] = `
"setRouteLeaveHook": [MockFunction],
}
}
- settings={Array []}
/>
</div>
</Fragment>
diff --git a/server/sonar-web/src/main/js/apps/create/project/constants.ts b/server/sonar-web/src/main/js/apps/create/project/constants.ts
index 68567ef7eea..d47426c1831 100644
--- a/server/sonar-web/src/main/js/apps/create/project/constants.ts
+++ b/server/sonar-web/src/main/js/apps/create/project/constants.ts
@@ -1,5 +1,3 @@
-import { AlmKeys } from '../../../types/alm-settings';
-
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
@@ -22,5 +20,3 @@ import { AlmKeys } from '../../../types/alm-settings';
export const PROJECT_NAME_MAX_LEN = 255;
export const DEFAULT_BBS_PAGE_SIZE = 25;
-
-export const ALLOWED_MULTIPLE_CONFIGS = [AlmKeys.GitLab, AlmKeys.Azure, AlmKeys.GitHub];
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx b/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx
index 97abfd16f81..b764b4dbd14 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx
@@ -31,7 +31,6 @@ import { hasGlobalPermission } from '../../../helpers/users';
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
import { Permissions } from '../../../types/permissions';
import { LoggedInUser } from '../../../types/users';
-import { ALLOWED_MULTIPLE_CONFIGS } from '../../create/project/constants';
import ProjectCreationMenuItem from './ProjectCreationMenuItem';
interface Props {
@@ -80,18 +79,10 @@ export class ProjectCreationMenu extends React.PureComponent<Props, State> {
const almSettings: AlmSettingsInstance[] = await getAlmSettings().catch(() => []);
- // Import is only available if exactly one binding is configured
const boundAlms = IMPORT_COMPATIBLE_ALMS.filter((key) => {
- let currentAlmSettings: AlmSettingsInstance[];
- if (key === AlmKeys.BitbucketServer || key === AlmKeys.BitbucketCloud) {
- currentAlmSettings = almSettings.filter(
- (s) => s.alm === AlmKeys.BitbucketCloud || s.alm === AlmKeys.BitbucketServer
- );
- } else {
- currentAlmSettings = almSettings.filter((s) => s.alm === key);
- }
+ const currentAlmSettings = almSettings.filter((s) => s.alm === key);
return (
- this.configLengthChecker(key, currentAlmSettings.length) &&
+ currentAlmSettings.length > 0 &&
key === currentAlmSettings[0].alm &&
this.almSettingIsValid(currentAlmSettings[0])
);
@@ -104,10 +95,6 @@ export class ProjectCreationMenu extends React.PureComponent<Props, State> {
}
};
- configLengthChecker = (key: AlmKeys, length: number) => {
- return ALLOWED_MULTIPLE_CONFIGS.includes(key) ? length > 0 : length === 1;
- };
-
render() {
const { className, currentUser } = this.props;
const { boundAlms } = this.state;
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx
index a73c1ea5999..87b621ecebe 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx
@@ -117,11 +117,22 @@ it('should filter alm bindings appropriately', async () => {
wrapper = shallowRender();
await waitAndUpdate(wrapper);
- expect(wrapper.state().boundAlms).toEqual([AlmKeys.Azure, AlmKeys.GitHub, AlmKeys.GitLab]);
+ expect(wrapper.state().boundAlms).toEqual([
+ AlmKeys.Azure,
+ AlmKeys.BitbucketServer,
+ AlmKeys.BitbucketCloud,
+ AlmKeys.GitHub,
+ AlmKeys.GitLab,
+ ]);
wrapper = shallowRender();
await waitAndUpdate(wrapper);
- expect(wrapper.state().boundAlms).toEqual([AlmKeys.Azure, AlmKeys.GitHub, AlmKeys.GitLab]);
+ expect(wrapper.state().boundAlms).toEqual([
+ AlmKeys.Azure,
+ AlmKeys.BitbucketServer,
+ AlmKeys.GitHub,
+ AlmKeys.GitLab,
+ ]);
});
function shallowRender(overrides: Partial<ProjectCreationMenu['props']> = {}) {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx
index ee27acc7694..2d75e7a76d8 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx
@@ -38,13 +38,11 @@ import {
AlmSettingsBindingStatusType,
} from '../../../../types/alm-settings';
import { EditionKey } from '../../../../types/editions';
-import { ALLOWED_MULTIPLE_CONFIGS } from '../../../create/project/constants';
export interface AlmBindingDefinitionBoxProps {
alm: AlmKeys;
branchesEnabled: boolean;
definition: AlmBindingDefinitionBase;
- multipleDefinitions: boolean;
onCheck: (definitionKey: string) => void;
onDelete: (definitionKey: string) => void;
onEdit: (definitionKey: string) => void;
@@ -108,23 +106,8 @@ function getPRDecorationFeatureStatus(
function getImportFeatureStatus(
alm: AlmKeys,
definition: AlmBindingDefinitionBase,
- multipleDefinitions: boolean,
type: AlmSettingsBindingStatusType.Success | AlmSettingsBindingStatusType.Failure
) {
- if (multipleDefinitions && !ALLOWED_MULTIPLE_CONFIGS.includes(alm)) {
- return (
- <div className="display-inline-flex-center">
- <strong className="spacer-left">
- {translate('settings.almintegration.feature.alm_repo_import.disabled')}
- </strong>
- <HelpTooltip
- className="little-spacer-left"
- overlay={translate('settings.almintegration.feature.alm_repo_import.disabled.multiple')}
- />
- </div>
- );
- }
-
if (!definition.url && alm !== AlmKeys.BitbucketCloud) {
return (
<div className="display-inline-flex-center">
@@ -156,7 +139,7 @@ function getPrDecoFeatureDescription(alm: AlmKeys) {
}
export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxProps) {
- const { alm, branchesEnabled, definition, multipleDefinitions, status = DEFAULT_STATUS } = props;
+ const { alm, branchesEnabled, definition, status = DEFAULT_STATUS } = props;
return (
<div className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition">
@@ -202,7 +185,7 @@ export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxPr
{translate('settings.almintegration.feature.alm_repo_import.title')}
</span>
</Tooltip>
- {getImportFeatureStatus(alm, definition, multipleDefinitions, status.type)}
+ {getImportFeatureStatus(alm, definition, status.type)}
</div>
)}
</div>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx
index 6e1382cc881..f36e4f931c7 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx
@@ -107,7 +107,6 @@ export default function AlmTabRenderer(props: AlmTabRendererProps) {
branchesEnabled={branchesEnabled}
definition={def}
key={def.key}
- multipleDefinitions={definitions.length > 1}
onCheck={props.onCheck}
onDelete={props.onDelete}
onEdit={props.onEdit}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx
index 8a1f5e2754c..e32365f2f57 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx
@@ -31,7 +31,6 @@ import AlmBindingDefinitionBox, { AlmBindingDefinitionBoxProps } from '../AlmBin
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
- expect(shallowRender({ multipleDefinitions: true })).toMatchSnapshot('multiple definitions');
expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
@@ -106,7 +105,6 @@ function shallowRender(props: Partial<AlmBindingDefinitionBoxProps> = {}) {
alm={AlmKeys.GitHub}
branchesEnabled={true}
definition={mockGithubBindingDefinition()}
- multipleDefinitions={false}
onCheck={jest.fn()}
onDelete={jest.fn()}
onEdit={jest.fn()}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap
index 4afcf1ec133..afbd6543c06 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap
@@ -164,48 +164,6 @@ exports[`should render correctly: error 1`] = `
</div>
`;
-exports[`should render correctly: multiple definitions 1`] = `
-<div
- className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
->
- <div
- className="actions pull-right"
- >
- <Button
- onClick={[Function]}
- >
- <EditIcon
- className="spacer-right"
- />
- edit
- </Button>
- <Button
- className="button-red spacer-left"
- onClick={[Function]}
- >
- <DeleteIcon
- className="spacer-right"
- />
- delete
- </Button>
- </div>
- <div
- className="big-spacer-bottom"
- >
- <h3>
- key
- </h3>
- <span>
- http://github.enterprise.com
- </span>
- </div>
- <i
- className="spinner spacer-right"
- />
- settings.almintegration.checking_configuration
-</div>
-`;
-
exports[`should render correctly: success 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap
index 20c590100f6..9adea1fe647 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap
@@ -39,7 +39,6 @@ exports[`should render correctly for multi-ALM binding: editing a definition 1`]
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -88,7 +87,6 @@ exports[`should render correctly for multi-ALM binding: loaded 1`] = `
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -137,7 +135,6 @@ exports[`should render correctly for multi-ALM binding: loading ALM definitions
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -186,7 +183,6 @@ exports[`should render correctly for multi-ALM binding: loading project count 1`
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -235,7 +231,6 @@ exports[`should render correctly for single-ALM binding 1`] = `
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -284,7 +279,6 @@ exports[`should render correctly for single-ALM binding 2`] = `
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -333,7 +327,6 @@ exports[`should render correctly for single-ALM binding 3`] = `
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -426,7 +419,6 @@ exports[`should render correctly with validation: create a second 1`] = `
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -480,7 +472,6 @@ exports[`should render correctly with validation: default 1`] = `
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
@@ -570,7 +561,6 @@ exports[`should render correctly with validation: pass the correct key for bitbu
}
}
key="key"
- multipleDefinitions={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
diff --git a/server/sonar-web/src/main/js/types/alm-settings.ts b/server/sonar-web/src/main/js/types/alm-settings.ts
index f6609284236..8487e41e2f9 100644
--- a/server/sonar-web/src/main/js/types/alm-settings.ts
+++ b/server/sonar-web/src/main/js/types/alm-settings.ts
@@ -25,6 +25,13 @@ export const enum AlmKeys {
GitLab = 'gitlab',
}
+export type AlmKeysUnion =
+ | AlmKeys.Azure
+ | AlmKeys.BitbucketServer
+ | AlmKeys.BitbucketCloud
+ | AlmKeys.GitHub
+ | AlmKeys.GitLab;
+
export type AlmBindingDefinition =
| AzureBindingDefinition
| GithubBindingDefinition