@@ -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,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} |
@@ -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} | |||
/> |
@@ -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)} |
@@ -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} | |||
/> |
@@ -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> |
@@ -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} | |||
/> | |||
); | |||
} |
@@ -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} | |||
/> | |||
); |
@@ -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} | |||
/> |
@@ -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()} |
@@ -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()} |
@@ -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, |
@@ -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", |
@@ -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} |
@@ -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} |
@@ -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]} |
@@ -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" | |||
> |
@@ -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> |
@@ -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]; |
@@ -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; |
@@ -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']> = {}) { |
@@ -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> |
@@ -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} |
@@ -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()} |
@@ -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" |
@@ -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]} |
@@ -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 |
@@ -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 |