소스 검색

SONAR-17588 Allow project onboarding when multiple Bitbucket integrations are configured

tags/9.8.0.63668
Revanshu Paliwal 1 년 전
부모
커밋
9d2a38de33
28개의 변경된 파일547개의 추가작업 그리고 231개의 파일을 삭제
  1. 17
    16
      server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx
  2. 30
    16
      server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx
  3. 16
    5
      server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx
  4. 31
    20
      server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx
  5. 15
    5
      server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx
  6. 17
    38
      server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx
  7. 2
    2
      server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
  8. 3
    3
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx
  9. 4
    2
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx
  10. 3
    3
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx
  11. 5
    3
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx
  12. 7
    3
      server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx
  13. 12
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap
  14. 62
    0
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap
  15. 30
    10
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap
  16. 107
    0
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap
  17. 152
    0
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap
  18. 2
    2
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap
  19. 0
    4
      server/sonar-web/src/main/js/apps/create/project/constants.ts
  20. 2
    15
      server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx
  21. 13
    2
      server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx
  22. 2
    19
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx
  23. 0
    1
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx
  24. 0
    2
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx
  25. 0
    42
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap
  26. 0
    10
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap
  27. 7
    0
      server/sonar-web/src/main/js/types/alm-settings.ts
  28. 8
    7
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 17
- 16
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>
);
}

+ 30
- 16
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}

+ 16
- 5
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}
/>

+ 31
- 20
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)}

+ 15
- 5
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}
/>

+ 17
- 38
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>

+ 2
- 2
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}
/>
);
}

+ 3
- 3
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}
/>
);

+ 4
- 2
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}
/>

+ 3
- 3
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()}

+ 5
- 3
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()}

+ 7
- 3
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,

+ 12
- 1
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",

+ 62
- 0
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}

+ 30
- 10
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}

+ 107
- 0
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]}

+ 152
- 0
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap 파일 보기

@@ -55,6 +55,27 @@ exports[`should render correctly: default 1`] = `
</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/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"
>
@@ -185,6 +206,27 @@ exports[`should render correctly: invalid configs, admin 1`] = `
</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/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"
>
@@ -315,6 +357,37 @@ exports[`should render correctly: invalid configs, admin 2`] = `
</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/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"
>
@@ -445,6 +518,27 @@ exports[`should render correctly: invalid configs, not admin 1`] = `
</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/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"
>
@@ -577,6 +671,33 @@ exports[`should render correctly: loading instances 1`] = `
</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/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"
>
@@ -734,6 +855,37 @@ exports[`should render correctly: no alm conf yet, admin 1`] = `
</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/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"
>

+ 2
- 2
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>

+ 0
- 4
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];

+ 2
- 15
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;

+ 13
- 2
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']> = {}) {

+ 2
- 19
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>

+ 0
- 1
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}

+ 0
- 2
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()}

+ 0
- 42
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"

+ 0
- 10
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]}

+ 7
- 0
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

+ 8
- 7
sonar-core/src/main/resources/org/sonar/l10n/core.properties 파일 보기

@@ -2122,8 +2122,8 @@ my_account.create_new.TRK=Add a project
my_account.add_project=Add Project
my_account.add_project.manual=Manually
my_account.add_project.azure=Azure DevOps
my_account.add_project.bitbucket=Bitbucket
my_account.add_project.bitbucketcloud=Bitbucket
my_account.add_project.bitbucket=Bitbucket Server
my_account.add_project.bitbucketcloud=Bitbucket Cloud
my_account.add_project.github=GitHub
my_account.add_project.gitlab=GitLab
my_account.reset_password=Update your password
@@ -3487,7 +3487,8 @@ onboarding.create_project.select_method.devops_platform=Do you want to benefit f
onboarding.create_project.select_method.no_alm_yet.admin=First, you need to set up a DevOps platform configuration.
onboarding.create_project.select_method.manual=Manually
onboarding.create_project.select_method.azure=From Azure DevOps
onboarding.create_project.select_method.bitbucket=From Bitbucket
onboarding.create_project.select_method.bitbucket=From Bitbucket Server
onboarding.create_project.select_method.bitbucketcloud=From Bitbucket Cloud
onboarding.create_project.select_method.github=From GitHub
onboarding.create_project.select_method.gitlab=From GitLab
onboarding.create_project.alm_not_configured=Contact admin to set up global configuration
@@ -3516,7 +3517,7 @@ onboarding.create_project.search_projects_repositories=Search for projects and r
onboarding.create_project.search_repositories=Search for a repository
onboarding.create_project.select_repositories=Select repositories
onboarding.create_project.select_all_repositories=Select all available repositories
onboarding.create_project.from_bbs=Create a project from Bitbucket Server
onboarding.create_project.from_bbs=Bitbucket Server project onboarding

onboarding.create_application.key.description=If specified, this value is used as the key instead of generating it from the name of the Application. Only letters, digits, dashes and underscores can be used.

@@ -3532,8 +3533,8 @@ onboarding.create_project.pat_form.pat_required=Please enter a personal access t
onboarding.create_project.pat_form.list_repositories=List repositories
onboarding.create_project.select_method=How do you want to create your project?
onboarding.create_project.too_many_alm_instances_X=This method requires exactly one {0} configuration.
onboarding.create_project.wrong_binding_count=You must have exactly 1 {alm} instance configured in order to use this method, but none were found. Either create the project manually, or contact your system administrator.
onboarding.create_project.wrong_binding_count.admin=You must have exactly 1 {alm} instance configured in order to use this method. You can configure instances under {url}.
onboarding.create_project.wrong_binding_count=You must have at least 1 {alm} instance configured in order to use this method, but none were found. Either create the project manually, or contact your system administrator.
onboarding.create_project.wrong_binding_count.admin=You must have at least 1 {alm} instance configured in order to use this method. You can configure instances under {url}.
onboarding.create_project.azure.no_url.admin=Your Azure DevOps instance configuration is missing a URL. We cannot import projects in the current state. You can configure instances under {url}.
onboarding.create_project.azure.no_url=Your Azure DevOps instance configuration is missing a URL. We cannot import projects in the current state. Please contact your system administrator.
onboarding.create_project.enter_pat=Enter personal access token
@@ -3589,7 +3590,7 @@ onboarding.create_project.azure.no_projects=No projects could be fetched from Az
onboarding.create_project.azure.search_results_for_project_X=Search results for "{0}"
onboarding.create_project.azure.no_repositories=Could not fetch repositories for this project. Contact your system administrator, or {link}.
onboarding.create_project.azure.no_results=No repositories match your search query.
onboarding.create_project.bitbucketcloud.title=Which Bitbucket Cloud repository do you want to set up?
onboarding.create_project.bitbucketcloud.title=Bitbucket Cloud project onboarding
onboarding.create_project.bitbucketcloud.no_projects=No projects could be fetched from Bitbucket. Contact your system administrator, or {link}.
onboarding.create_project.bitbucketcloud.link=See on Bitbucket
onboarding.create_project.github.title=Github project onboarding

Loading…
취소
저장