@@ -86,6 +86,7 @@ export function deletePortfolio(portfolio: string): Promise<void | Response> { | |||
export function createProject(data: { | |||
name: string; | |||
project: string; | |||
mainBranch: string; | |||
visibility?: Visibility; | |||
}): Promise<{ project: ProjectBase }> { | |||
return postJSON('/api/projects/create', data).catch(throwGlobalError); |
@@ -18,9 +18,12 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import classNames from 'classnames'; | |||
import { debounce } from 'lodash'; | |||
import { debounce, isEmpty } from 'lodash'; | |||
import * as React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { createProject, doesComponentExists } from '../../../api/components'; | |||
import { getValue } from '../../../api/settings'; | |||
import DocLink from '../../../components/common/DocLink'; | |||
import ProjectKeyInput from '../../../components/common/ProjectKeyInput'; | |||
import { SubmitButton } from '../../../components/controls/buttons'; | |||
import ValidationInput from '../../../components/controls/ValidationInput'; | |||
@@ -30,6 +33,7 @@ import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsEx | |||
import { translate } from '../../../helpers/l10n'; | |||
import { PROJECT_KEY_INVALID_CHARACTERS, validateProjectKey } from '../../../helpers/projects'; | |||
import { ProjectKeyValidationResult } from '../../../types/component'; | |||
import { GlobalSettingKeys } from '../../../types/settings'; | |||
import { PROJECT_NAME_MAX_LEN } from './constants'; | |||
import CreateProjectPageHeader from './CreateProjectPageHeader'; | |||
import './ManualProjectCreate.css'; | |||
@@ -47,6 +51,9 @@ interface State { | |||
projectKeyError?: string; | |||
projectKeyTouched: boolean; | |||
validatingProjectKey: boolean; | |||
mainBranchName: string; | |||
mainBranchNameError?: string; | |||
mainBranchNameTouched: boolean; | |||
submitting: boolean; | |||
} | |||
@@ -63,6 +70,8 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
submitting: false, | |||
projectKeyTouched: false, | |||
projectNameTouched: false, | |||
mainBranchName: 'main', | |||
mainBranchNameTouched: false, | |||
validatingProjectKey: false | |||
}; | |||
this.checkFreeKey = debounce(this.checkFreeKey, 250); | |||
@@ -70,12 +79,21 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
componentDidMount() { | |||
this.mounted = true; | |||
this.fetchMainBranchName(); | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
} | |||
fetchMainBranchName = async () => { | |||
const mainBranchName = await getValue({ key: GlobalSettingKeys.MainBranchName }); | |||
if (this.mounted && mainBranchName.value !== undefined) { | |||
this.setState({ mainBranchName: mainBranchName.value }); | |||
} | |||
}; | |||
checkFreeKey = (key: string) => { | |||
this.setState({ validatingProjectKey: true }); | |||
@@ -98,23 +116,25 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
}; | |||
canSubmit(state: State): state is ValidState { | |||
const { projectKey, projectKeyError, projectName, projectNameError } = state; | |||
const { projectKey, projectKeyError, projectName, projectNameError, mainBranchName } = state; | |||
return Boolean( | |||
projectKeyError === undefined && | |||
projectNameError === undefined && | |||
projectKey.length > 0 && | |||
projectName.length > 0 | |||
!isEmpty(projectKey) && | |||
!isEmpty(projectName) && | |||
!isEmpty(mainBranchName) | |||
); | |||
} | |||
handleFormSubmit = (event: React.FormEvent<HTMLFormElement>) => { | |||
event.preventDefault(); | |||
const { state } = this; | |||
if (this.canSubmit(state)) { | |||
const { projectKey, projectName, mainBranchName } = this.state; | |||
if (this.canSubmit(this.state)) { | |||
this.setState({ submitting: true }); | |||
createProject({ | |||
project: state.projectKey, | |||
name: (state.projectName || state.projectKey).trim() | |||
project: projectKey, | |||
name: (projectName || projectKey).trim(), | |||
mainBranch: mainBranchName | |||
}).then( | |||
({ project }) => this.props.onProjectCreate(project.key), | |||
() => { | |||
@@ -158,6 +178,14 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
); | |||
}; | |||
handleBranchNameChange = (mainBranchName: string, fromUI = false) => { | |||
this.setState({ | |||
mainBranchName, | |||
mainBranchNameError: this.validateMainBranchName(mainBranchName), | |||
mainBranchNameTouched: fromUI | |||
}); | |||
}; | |||
validateKey = (projectKey: string) => { | |||
const result = validateProjectKey(projectKey); | |||
return result === ProjectKeyValidationResult.Valid | |||
@@ -166,12 +194,19 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
}; | |||
validateName = (projectName: string) => { | |||
if (projectName.length === 0) { | |||
if (isEmpty(projectName)) { | |||
return translate('onboarding.create_project.display_name.error.empty'); | |||
} | |||
return undefined; | |||
}; | |||
validateMainBranchName = (mainBranchName: string) => { | |||
if (isEmpty(mainBranchName)) { | |||
return translate('onboarding.create_project.main_branch_name.error.empty'); | |||
} | |||
return undefined; | |||
}; | |||
render() { | |||
const { | |||
projectKey, | |||
@@ -181,13 +216,18 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
projectNameError, | |||
projectNameTouched, | |||
validatingProjectKey, | |||
mainBranchName, | |||
mainBranchNameError, | |||
mainBranchNameTouched, | |||
submitting | |||
} = this.state; | |||
const { branchesEnabled } = this.props; | |||
const touched = !!(projectKeyTouched || projectNameTouched); | |||
const touched = Boolean(projectKeyTouched || projectNameTouched); | |||
const projectNameIsInvalid = projectNameTouched && projectNameError !== undefined; | |||
const projectNameIsValid = projectNameTouched && projectNameError === undefined; | |||
const mainBranchNameIsValid = mainBranchNameTouched && mainBranchNameError === undefined; | |||
const mainBranchNameIsInvalid = mainBranchNameTouched && mainBranchNameError !== undefined; | |||
return ( | |||
<> | |||
@@ -230,6 +270,42 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat | |||
validating={validatingProjectKey} | |||
/> | |||
<ValidationInput | |||
className="form-field" | |||
description={ | |||
<FormattedMessage | |||
id="onboarding.create_project.main_branch_name.description" | |||
defaultMessage={translate( | |||
'onboarding.create_project.main_branch_name.description' | |||
)} | |||
values={{ | |||
learn_more: ( | |||
<DocLink to="/project-administration/project-existence"> | |||
{translate('learn_more')} | |||
</DocLink> | |||
) | |||
}} | |||
/> | |||
} | |||
error={mainBranchNameError} | |||
id="main-branch-name" | |||
isInvalid={mainBranchNameIsInvalid} | |||
isValid={mainBranchNameIsValid} | |||
label={translate('onboarding.create_project.main_branch_name')} | |||
required={true}> | |||
<input | |||
id="main-branch-name" | |||
className={classNames('input-super-large', { | |||
'is-invalid': mainBranchNameIsInvalid, | |||
'is-valid': mainBranchNameIsValid | |||
})} | |||
minLength={1} | |||
onChange={e => this.handleBranchNameChange(e.currentTarget.value, true)} | |||
type="text" | |||
value={mainBranchName} | |||
/> | |||
</ValidationInput> | |||
<SubmitButton disabled={!this.canSubmit(this.state) || submitting}> | |||
{translate('set_up')} | |||
</SubmitButton> |
@@ -31,6 +31,10 @@ jest.mock('../../../../api/components', () => ({ | |||
.mockImplementation(({ component }) => Promise.resolve(component === 'exists')) | |||
})); | |||
jest.mock('../../../../api/settings', () => ({ | |||
getValue: jest.fn().mockResolvedValue({ value: 'main' }) | |||
})); | |||
beforeEach(() => { | |||
jest.clearAllMocks(); | |||
}); | |||
@@ -70,12 +74,11 @@ it('should validate form input', async () => { | |||
).toHaveValue('This-is-not-a-key-'); | |||
// Clear name | |||
await user.click( | |||
await screen.findByRole('textbox', { | |||
await user.clear( | |||
screen.getByRole('textbox', { | |||
name: 'onboarding.create_project.display_name field_required' | |||
}) | |||
); | |||
await user.keyboard('{Control>}a{/Control}{Backspace}'); | |||
expect( | |||
screen.getByRole('textbox', { name: 'onboarding.create_project.project_key field_required' }) | |||
).toHaveValue(''); | |||
@@ -117,6 +120,16 @@ it('should validate form input', async () => { | |||
expect( | |||
await screen.findByText('onboarding.create_project.project_key.taken') | |||
).toBeInTheDocument(); | |||
// Invalid main branch name | |||
await user.clear( | |||
screen.getByRole('textbox', { | |||
name: 'onboarding.create_project.main_branch_name field_required' | |||
}) | |||
); | |||
expect( | |||
await screen.findByText('onboarding.create_project.main_branch_name.error.empty') | |||
).toBeInTheDocument(); | |||
}); | |||
it('should submit form input', async () => { | |||
@@ -132,7 +145,11 @@ it('should submit form input', async () => { | |||
); | |||
await user.keyboard('test'); | |||
await user.click(screen.getByRole('button', { name: 'set_up' })); | |||
expect(createProject).toHaveBeenCalledWith({ name: 'test', project: 'test' }); | |||
expect(createProject).toHaveBeenCalledWith({ | |||
name: 'test', | |||
project: 'test', | |||
mainBranch: 'main' | |||
}); | |||
expect(onProjectCreate).toHaveBeenCalled(); | |||
}); | |||
@@ -20,6 +20,7 @@ | |||
import * as React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { createProject } from '../../api/components'; | |||
import { getValue } from '../../api/settings'; | |||
import Link from '../../components/common/Link'; | |||
import VisibilitySelector from '../../components/common/VisibilitySelector'; | |||
import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons'; | |||
@@ -29,6 +30,7 @@ import MandatoryFieldMarker from '../../components/ui/MandatoryFieldMarker'; | |||
import MandatoryFieldsExplanation from '../../components/ui/MandatoryFieldsExplanation'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { getProjectUrl } from '../../helpers/urls'; | |||
import { GlobalSettingKeys } from '../../types/settings'; | |||
import { Visibility } from '../../types/types'; | |||
interface Props { | |||
@@ -45,6 +47,7 @@ interface State { | |||
visibility?: Visibility; | |||
// add index declaration to be able to do `this.setState({ [name]: value });` | |||
[x: string]: any; | |||
mainBranchName: string; | |||
} | |||
export default class CreateProjectForm extends React.PureComponent<Props, State> { | |||
@@ -57,12 +60,14 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> | |||
key: '', | |||
loading: false, | |||
name: '', | |||
visibility: props.defaultProjectVisibility | |||
visibility: props.defaultProjectVisibility, | |||
mainBranchName: 'main' | |||
}; | |||
} | |||
componentDidMount() { | |||
this.mounted = true; | |||
this.fetchMainBranchName(); | |||
} | |||
componentDidUpdate() { | |||
@@ -78,6 +83,14 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> | |||
this.mounted = false; | |||
} | |||
fetchMainBranchName = async () => { | |||
const mainBranchName = await getValue({ key: GlobalSettingKeys.MainBranchName }); | |||
if (this.mounted && mainBranchName.value !== undefined) { | |||
this.setState({ mainBranchName: mainBranchName.value }); | |||
} | |||
}; | |||
handleInputChange = (event: React.SyntheticEvent<HTMLInputElement>) => { | |||
const { name, value } = event.currentTarget; | |||
this.setState({ [name]: value }); | |||
@@ -89,11 +102,13 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> | |||
handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { | |||
event.preventDefault(); | |||
const { name, key, mainBranchName, visibility } = this.state; | |||
const data = { | |||
name: this.state.name, | |||
project: this.state.key, | |||
visibility: this.state.visibility | |||
name, | |||
project: key, | |||
mainBranch: mainBranchName, | |||
visibility | |||
}; | |||
this.setState({ loading: true }); | |||
@@ -159,7 +174,7 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> | |||
<MandatoryFieldsExplanation className="modal-field" /> | |||
<div className="modal-field"> | |||
<label htmlFor="create-project-name"> | |||
{translate('name')} | |||
{translate('onboarding.create_project.display_name')} | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
@@ -175,7 +190,7 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> | |||
</div> | |||
<div className="modal-field"> | |||
<label htmlFor="create-project-key"> | |||
{translate('key')} | |||
{translate('onboarding.create_project.project_key')} | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
@@ -188,6 +203,21 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> | |||
value={this.state.key} | |||
/> | |||
</div> | |||
<div className="modal-field"> | |||
<label htmlFor="create-project-main-branch-name"> | |||
{translate('onboarding.create_project.main_branch_name')} | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
id="create-project-main-branch-name" | |||
maxLength={400} | |||
name="mainBranchName" | |||
onChange={this.handleInputChange} | |||
required={true} | |||
type="text" | |||
value={this.state.mainBranchName} | |||
/> | |||
</div> | |||
<div className="modal-field"> | |||
<label>{translate('visibility')}</label> | |||
<VisibilitySelector |
@@ -17,49 +17,67 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first */ | |||
jest.mock('../../../api/components', () => ({ | |||
createProject: jest.fn(({ name }: { name: string }) => | |||
Promise.resolve({ project: { key: name, name } }) | |||
) | |||
})); | |||
import { shallow } from 'enzyme'; | |||
import { render, screen } from '@testing-library/react'; | |||
import userEvent from '@testing-library/user-event'; | |||
import * as React from 'react'; | |||
import { change, submit, waitAndUpdate } from '../../../helpers/testUtils'; | |||
import { createProject } from '../../../api/components'; | |||
import CreateProjectForm from '../CreateProjectForm'; | |||
const createProject = require('../../../api/components').createProject as jest.Mock<any>; | |||
jest.mock('../../../api/components', () => ({ | |||
createProject: jest.fn().mockResolvedValue({}), | |||
doesComponentExists: jest | |||
.fn() | |||
.mockImplementation(({ component }) => Promise.resolve(component === 'exists')) | |||
})); | |||
jest.mock('../../../api/settings', () => ({ | |||
getValue: jest.fn().mockResolvedValue({ value: 'main' }) | |||
})); | |||
beforeEach(() => { | |||
jest.clearAllMocks(); | |||
}); | |||
it('should render all inputs and create a project', async () => { | |||
const user = userEvent.setup(); | |||
renderCreateProjectForm(); | |||
it('creates project', async () => { | |||
const wrapper = shallow( | |||
<CreateProjectForm | |||
defaultProjectVisibility="public" | |||
onClose={jest.fn()} | |||
onProjectCreated={jest.fn()} | |||
/> | |||
await user.type( | |||
screen.getByRole('textbox', { | |||
name: 'onboarding.create_project.display_name field_required' | |||
}), | |||
'ProjectName' | |||
); | |||
(wrapper.instance() as CreateProjectForm).mounted = true; | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input[name="name"]'), 'name', { | |||
currentTarget: { name: 'name', value: 'name' } | |||
}); | |||
change(wrapper.find('input[name="key"]'), 'key', { | |||
currentTarget: { name: 'key', value: 'key' } | |||
}); | |||
wrapper.find('VisibilitySelector').prop<Function>('onChange')('private'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
await user.type( | |||
screen.getByRole('textbox', { | |||
name: 'onboarding.create_project.project_key field_required' | |||
}), | |||
'ProjectKey' | |||
); | |||
expect( | |||
screen.getByRole('textbox', { | |||
name: 'onboarding.create_project.main_branch_name field_required' | |||
}) | |||
).toHaveValue('main'); | |||
submit(wrapper.find('form')); | |||
await user.type( | |||
screen.getByRole('textbox', { | |||
name: 'onboarding.create_project.main_branch_name field_required' | |||
}), | |||
'{Control>}a{/Control}{Backspace}ProjectMainBranch' | |||
); | |||
await user.click(screen.getByRole('button', { name: 'create' })); | |||
expect(createProject).toHaveBeenCalledWith({ | |||
name: 'name', | |||
project: 'key', | |||
visibility: 'private' | |||
name: 'ProjectName', | |||
project: 'ProjectKey', | |||
mainBranch: 'ProjectMainBranch' | |||
}); | |||
expect(wrapper).toMatchSnapshot(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
function renderCreateProjectForm(props: Partial<CreateProjectForm['props']> = {}) { | |||
render(<CreateProjectForm onClose={jest.fn()} onProjectCreated={jest.fn()} {...props} />); | |||
} |
@@ -1,343 +0,0 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`creates project 1`] = ` | |||
<Modal | |||
contentLabel="modal form" | |||
onRequestClose={[MockFunction]} | |||
> | |||
<form | |||
id="create-project-form" | |||
onSubmit={[Function]} | |||
> | |||
<header | |||
className="modal-head" | |||
> | |||
<h2> | |||
qualifiers.create.TRK | |||
</h2> | |||
</header> | |||
<div | |||
className="modal-body" | |||
> | |||
<MandatoryFieldsExplanation | |||
className="modal-field" | |||
/> | |||
<div | |||
className="modal-field" | |||
> | |||
<label | |||
htmlFor="create-project-name" | |||
> | |||
name | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
autoFocus={true} | |||
id="create-project-name" | |||
maxLength={2000} | |||
name="name" | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
</div> | |||
<div | |||
className="modal-field" | |||
> | |||
<label | |||
htmlFor="create-project-key" | |||
> | |||
key | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
id="create-project-key" | |||
maxLength={400} | |||
name="key" | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
</div> | |||
<div | |||
className="modal-field" | |||
> | |||
<label> | |||
visibility | |||
</label> | |||
<VisibilitySelector | |||
canTurnToPrivate={true} | |||
className="little-spacer-top" | |||
onChange={[Function]} | |||
visibility="public" | |||
/> | |||
</div> | |||
</div> | |||
<footer | |||
className="modal-foot" | |||
> | |||
<SubmitButton | |||
disabled={false} | |||
id="create-project-submit" | |||
> | |||
create | |||
</SubmitButton> | |||
<ResetButtonLink | |||
id="create-project-cancel" | |||
onClick={[MockFunction]} | |||
> | |||
cancel | |||
</ResetButtonLink> | |||
</footer> | |||
</form> | |||
</Modal> | |||
`; | |||
exports[`creates project 2`] = ` | |||
<Modal | |||
contentLabel="modal form" | |||
onRequestClose={[MockFunction]} | |||
> | |||
<form | |||
id="create-project-form" | |||
onSubmit={[Function]} | |||
> | |||
<header | |||
className="modal-head" | |||
> | |||
<h2> | |||
qualifiers.create.TRK | |||
</h2> | |||
</header> | |||
<div | |||
className="modal-body" | |||
> | |||
<MandatoryFieldsExplanation | |||
className="modal-field" | |||
/> | |||
<div | |||
className="modal-field" | |||
> | |||
<label | |||
htmlFor="create-project-name" | |||
> | |||
name | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
autoFocus={true} | |||
id="create-project-name" | |||
maxLength={2000} | |||
name="name" | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="name" | |||
/> | |||
</div> | |||
<div | |||
className="modal-field" | |||
> | |||
<label | |||
htmlFor="create-project-key" | |||
> | |||
key | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
id="create-project-key" | |||
maxLength={400} | |||
name="key" | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="key" | |||
/> | |||
</div> | |||
<div | |||
className="modal-field" | |||
> | |||
<label> | |||
visibility | |||
</label> | |||
<VisibilitySelector | |||
canTurnToPrivate={true} | |||
className="little-spacer-top" | |||
onChange={[Function]} | |||
visibility="private" | |||
/> | |||
</div> | |||
</div> | |||
<footer | |||
className="modal-foot" | |||
> | |||
<SubmitButton | |||
disabled={false} | |||
id="create-project-submit" | |||
> | |||
create | |||
</SubmitButton> | |||
<ResetButtonLink | |||
id="create-project-cancel" | |||
onClick={[MockFunction]} | |||
> | |||
cancel | |||
</ResetButtonLink> | |||
</footer> | |||
</form> | |||
</Modal> | |||
`; | |||
exports[`creates project 3`] = ` | |||
<Modal | |||
contentLabel="modal form" | |||
onRequestClose={[MockFunction]} | |||
> | |||
<form | |||
id="create-project-form" | |||
onSubmit={[Function]} | |||
> | |||
<header | |||
className="modal-head" | |||
> | |||
<h2> | |||
qualifiers.create.TRK | |||
</h2> | |||
</header> | |||
<div | |||
className="modal-body" | |||
> | |||
<MandatoryFieldsExplanation | |||
className="modal-field" | |||
/> | |||
<div | |||
className="modal-field" | |||
> | |||
<label | |||
htmlFor="create-project-name" | |||
> | |||
name | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
autoFocus={true} | |||
id="create-project-name" | |||
maxLength={2000} | |||
name="name" | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="name" | |||
/> | |||
</div> | |||
<div | |||
className="modal-field" | |||
> | |||
<label | |||
htmlFor="create-project-key" | |||
> | |||
key | |||
<MandatoryFieldMarker /> | |||
</label> | |||
<input | |||
id="create-project-key" | |||
maxLength={400} | |||
name="key" | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="key" | |||
/> | |||
</div> | |||
<div | |||
className="modal-field" | |||
> | |||
<label> | |||
visibility | |||
</label> | |||
<VisibilitySelector | |||
canTurnToPrivate={true} | |||
className="little-spacer-top" | |||
onChange={[Function]} | |||
visibility="private" | |||
/> | |||
</div> | |||
</div> | |||
<footer | |||
className="modal-foot" | |||
> | |||
<i | |||
className="spinner spacer-right" | |||
/> | |||
<SubmitButton | |||
disabled={true} | |||
id="create-project-submit" | |||
> | |||
create | |||
</SubmitButton> | |||
<ResetButtonLink | |||
id="create-project-cancel" | |||
onClick={[MockFunction]} | |||
> | |||
cancel | |||
</ResetButtonLink> | |||
</footer> | |||
</form> | |||
</Modal> | |||
`; | |||
exports[`creates project 4`] = ` | |||
<Modal | |||
contentLabel="modal form" | |||
onRequestClose={[MockFunction]} | |||
> | |||
<div> | |||
<header | |||
className="modal-head" | |||
> | |||
<h2> | |||
qualifiers.create.TRK | |||
</h2> | |||
</header> | |||
<div | |||
className="modal-body" | |||
> | |||
<Alert | |||
variant="success" | |||
> | |||
<FormattedMessage | |||
defaultMessage="projects_management.project_has_been_successfully_created" | |||
id="projects_management.project_has_been_successfully_created" | |||
values={ | |||
Object { | |||
"project": <ForwardRef(Link) | |||
to={ | |||
Object { | |||
"pathname": "/dashboard", | |||
"search": "?id=name", | |||
} | |||
} | |||
> | |||
name | |||
</ForwardRef(Link)>, | |||
} | |||
} | |||
/> | |||
</Alert> | |||
</div> | |||
<footer | |||
className="modal-foot" | |||
> | |||
<ResetButtonLink | |||
id="create-project-close" | |||
innerRef={[Function]} | |||
onClick={[MockFunction]} | |||
> | |||
close | |||
</ResetButtonLink> | |||
</footer> | |||
</div> | |||
</Modal> | |||
`; |
@@ -38,7 +38,8 @@ export enum GlobalSettingKeys { | |||
DeveloperAggregatedInfoDisabled = 'sonar.developerAggregatedInfo.disabled', | |||
UpdatecenterActivated = 'sonar.updatecenter.activate', | |||
DisplayAnnouncementMessage = 'sonar.announcement.displayMessage', | |||
AnnouncementMessage = 'sonar.announcement.message' | |||
AnnouncementMessage = 'sonar.announcement.message', | |||
MainBranchName = 'sonar.projectCreation.mainBranchName' | |||
} | |||
export type SettingDefinitionAndValue = { |
@@ -3499,6 +3499,11 @@ onboarding.create_project.project_key.taken=This project key is already taken. | |||
onboarding.create_project.display_name=Project display name | |||
onboarding.create_project.display_name.error.empty=The display name is required. | |||
onboarding.create_project.display_name.description=Up to 255 characters. Some scanners might override the value you provide. | |||
onboarding.create_project.main_branch_name=Main branch name | |||
onboarding.create_project.main_branch_name.error.empty=The main branch name is required. | |||
onboarding.create_project.main_branch_name.description=The name of your project’s default branch { learn_more } | |||
onboarding.create_project.pr_decoration.information=Manually created projects won’t benefit from the features associated with DevOps Platforms integration unless you configure them in the project settings. | |||
onboarding.create_project.repository_imported=Already set up | |||
onboarding.create_project.see_project=See the project |