gitlabSettings: AlmSettingsInstance[];
loading: boolean;
creatingAlmDefinition?: AlmKeys;
+ nbrOfProjects?: number;
}
const PROJECT_MODE_FOR_ALM_KEY = {
this.setState({ creatingAlmDefinition: alm });
};
- handleProjectSetupDone = (createProject: CreateProjectApiCallback) => {
+ handleProjectSetupDone = (createProject: CreateProjectApiCallback, nbrOfProjects?: number) => {
const { location, router } = this.props;
this.createProjectFnRef = createProject;
+ this.setState({ nbrOfProjects });
+
location.query.setncd = 'true';
router.push(location);
};
render() {
const { location, router } = this.props;
- const { creatingAlmDefinition } = this.state;
+ const { creatingAlmDefinition, nbrOfProjects } = this.state;
const mode: CreateProjectModes | undefined = location.query?.mode;
const isProjectSetupDone = location.query?.setncd === 'true';
const gridLayoutStyle = mode ? 'sw-col-start-2 sw-col-span-10' : 'sw-col-span-12';
<NewCodeDefinitionSelection
router={router}
createProjectFnRef={this.createProjectFnRef}
+ numberOfProjects={nbrOfProjects}
/>
</div>
interface Props {
canAdmin: boolean;
loadingBindings: boolean;
- onProjectSetupDone: (createProject: CreateProjectApiCallback) => void;
+ onProjectSetupDone: (createProject: CreateProjectApiCallback, nbrOfProjects: number) => void;
almInstances: AlmSettingsInstance[];
location: Location;
router: Router;
}
};
- handleImportRepository = (repoKey: string) => {
+ handleImportRepository = (repoKeys: string[]) => {
const { selectedOrganization, selectedAlmInstance } = this.state;
- if (selectedAlmInstance && selectedOrganization && repoKey !== '') {
+ if (selectedAlmInstance && selectedOrganization && repoKeys.length > 0) {
this.props.onProjectSetupDone(
setupGithubProjectCreation({
almSetting: selectedAlmInstance.key,
organization: selectedOrganization.key,
- repositoryKey: repoKey,
+ repositoryKey: repoKeys.join(','), // TBD
}),
+ repoKeys.length,
);
}
};
loadingBindings: boolean;
loadingOrganizations: boolean;
loadingRepositories: boolean;
- onImportRepository: (key: string) => void;
+ onImportRepository: (key: string[]) => void;
onLoadMore: () => void;
onSearch: (q: string) => void;
onSelectOrganization: (key: string) => void;
}
const handleImport = () => {
- props.onImportRepository(Array.from(selected).toString()); // TBD
+ props.onImportRepository(Array.from(selected));
};
const handleCheckAll = () => {
await user.click(importButton);
expect(
- screen.getByRole('heading', { name: 'onboarding.create_project.new_code_definition.title' }),
+ screen.getByRole('heading', { name: 'onboarding.create_x_project.new_code_definition.title1' }),
).toBeInTheDocument();
await user.click(screen.getByRole('radio', { name: 'new_code_definition.global_setting' }));
await user.click(
screen.getByRole('button', {
- name: 'onboarding.create_project.new_code_definition.create_project',
+ name: 'onboarding.create_project.new_code_definition.create_x_projects1',
}),
);
await user.click(importButton);
expect(
- screen.getByRole('heading', { name: 'onboarding.create_project.new_code_definition.title' }),
+ screen.getByRole('heading', { name: 'onboarding.create_x_project.new_code_definition.title1' }),
).toBeInTheDocument();
await user.click(screen.getByRole('radio', { name: 'new_code_definition.global_setting' }));
await user.click(
screen.getByRole('button', {
- name: 'onboarding.create_project.new_code_definition.create_project',
+ name: 'onboarding.create_project.new_code_definition.create_x_projects1',
}),
);
await user.click(setupButton);
expect(
- screen.getByRole('heading', { name: 'onboarding.create_project.new_code_definition.title' }),
+ screen.getByRole('heading', { name: 'onboarding.create_x_project.new_code_definition.title1' }),
).toBeInTheDocument();
await user.click(screen.getByRole('radio', { name: 'new_code_definition.global_setting' }));
await user.click(
screen.getByRole('button', {
- name: 'onboarding.create_project.new_code_definition.create_project',
+ name: 'onboarding.create_project.new_code_definition.create_x_projects1',
}),
);
project3Checkbox: byRole('listitem', { name: 'Github repo 3' }).byRole('checkbox'),
checkAll: byRole('checkbox', { name: 'onboarding.create_project.select_all_repositories' }),
importButton: byRole('button', { name: 'onboarding.create_project.import' }),
- newCodeTitle: byRole('heading', { name: 'onboarding.create_project.new_code_definition.title' }),
+ newCodeTitle: byRole('heading', {
+ name: 'onboarding.create_x_project.new_code_definition.title1',
+ }),
+ newCodeMultipleProjectTitle: byRole('heading', {
+ name: 'onboarding.create_x_project.new_code_definition.title2',
+ }),
+ changePeriodLaterInfo: byText('onboarding.create_projects.new_code_definition.change_info'),
createProjectButton: byRole('button', {
- name: 'onboarding.create_project.new_code_definition.create_project',
+ name: 'onboarding.create_project.new_code_definition.create_x_projects1',
+ }),
+ createProjectsButton: byRole('button', {
+ name: 'onboarding.create_project.new_code_definition.create_x_projects2',
}),
globalSettingRadio: byRole('radio', { name: 'new_code_definition.global_setting' }),
};
expect(ui.importButton.get()).toBeInTheDocument();
await user.click(ui.importButton.get());
- expect(await ui.newCodeTitle.find()).toBeInTheDocument();
+ expect(await ui.newCodeMultipleProjectTitle.find()).toBeInTheDocument();
+ expect(ui.changePeriodLaterInfo.get()).toBeInTheDocument();
+ expect(ui.createProjectsButton.get()).toBeDisabled();
- // TBD
+ await user.click(ui.globalSettingRadio.get());
+ expect(ui.createProjectsButton.get()).toBeEnabled();
});
it('should show search filter when the authentication is successful', async () => {
await user.click(importButton);
expect(
- screen.getByRole('heading', { name: 'onboarding.create_project.new_code_definition.title' }),
+ screen.getByRole('heading', { name: 'onboarding.create_x_project.new_code_definition.title1' }),
).toBeInTheDocument();
await user.click(screen.getByRole('radio', { name: 'new_code_definition.global_setting' }));
await user.click(
screen.getByRole('button', {
- name: 'onboarding.create_project.new_code_definition.create_project',
+ name: 'onboarding.create_project.new_code_definition.create_x_projects1',
}),
);
name: /onboarding.create_project.display_name/,
}),
projectNextButton: byRole('button', { name: 'next' }),
- newCodeDefinitionHeader: byText('onboarding.create_project.new_code_definition.title'),
+ newCodeDefinitionHeader: byText('onboarding.create_x_project.new_code_definition.title1'),
inheritGlobalNcdRadio: byRole('radio', { name: 'new_code_definition.global_setting' }),
projectCreateButton: byRole('button', {
- name: 'onboarding.create_project.new_code_definition.create_project',
+ name: 'onboarding.create_project.new_code_definition.create_x_projects1',
}),
overrideNcdRadio: byRole('radio', { name: 'new_code_definition.specific_setting' }),
ncdOptionPreviousVersionRadio: byRole('radio', {
onCheck,
onImport,
}: AlmRepoItemProps) {
- const labelId = `${almKey.replace(/\s/g, '_')}-label`;
+ const labelId = `${almKey.toString().replace(/\s/g, '_')}-label`;
return (
<RepositoryItem
selected={selected}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { ButtonPrimary, Link, Spinner, Title } from 'design-system';
+import { ButtonPrimary, ButtonSecondary, FlagMessage, Link, Spinner, Title } from 'design-system';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
+import { useNavigate } from 'react-router-dom';
import { Router } from '../../../../components/hoc/withRouter';
import NewCodeDefinitionSelector from '../../../../components/new-code-definition/NewCodeDefinitionSelector';
import { useDocUrl } from '../../../../helpers/docs';
interface Props {
createProjectFnRef: CreateProjectApiCallback | null;
router: Router;
+ numberOfProjects?: number;
}
export default function NewCodeDefinitionSelection(props: Props) {
- const { createProjectFnRef, router } = props;
+ const { createProjectFnRef, router, numberOfProjects } = props;
const [submitting, setSubmitting] = React.useState(false);
const [selectedDefinition, selectDefinition] = React.useState<NewCodeDefinitiondWithCompliance>();
+ const navigate = useNavigate();
+
const getDocUrl = useDocUrl();
+ const isMultipleProjects = numberOfProjects !== undefined && numberOfProjects !== 1;
+ const projectCount = isMultipleProjects ? numberOfProjects : 1;
+
const handleProjectCreation = React.useCallback(async () => {
if (createProjectFnRef && selectedDefinition) {
setSubmitting(true);
return (
<div id="project-ncd-selection" className="sw-body-sm">
- <Title>{translate('onboarding.create_project.new_code_definition.title')}</Title>
+ <Title>
+ <FormattedMessage
+ defaultMessage={translate('onboarding.create_x_project.new_code_definition.title')}
+ id="onboarding.create_x_project.new_code_definition.title"
+ values={{
+ count: projectCount,
+ }}
+ />
+ </Title>
<p className="sw-mb-2">
<FormattedMessage
/>
</p>
- <NewCodeDefinitionSelector onNcdChanged={selectDefinition} />
+ <NewCodeDefinitionSelector
+ onNcdChanged={selectDefinition}
+ isMultipleProjects={isMultipleProjects}
+ />
+
+ {isMultipleProjects && (
+ <FlagMessage variant="info">
+ {translate('onboarding.create_projects.new_code_definition.change_info')}
+ </FlagMessage>
+ )}
<div className="sw-mt-10 sw-mb-8">
+ <ButtonSecondary className="sw-mr-2" onClick={() => navigate(-1)}>
+ {translate('back')}
+ </ButtonSecondary>
<ButtonPrimary
onClick={handleProjectCreation}
disabled={!selectedDefinition?.isCompliant || submitting}
type="submit"
>
- {translate('onboarding.create_project.new_code_definition.create_project')}
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.create_project.new_code_definition.create_x_projects',
+ )}
+ id="onboarding.create_project.new_code_definition.create_x_projects"
+ values={{
+ count: projectCount,
+ }}
+ />
<Spinner className="sw-ml-2" loading={submitting} />
</ButtonPrimary>
</div>
interface Props {
onNcdChanged: (ncd: NewCodeDefinitiondWithCompliance) => void;
+ isMultipleProjects?: boolean;
}
export default function NewCodeDefinitionSelector(props: Props) {
- const { onNcdChanged } = props;
+ const { onNcdChanged, isMultipleProjects } = props;
const [globalNcd, setGlobalNcd] = React.useState<NewCodeDefinition | null>(null);
const [selectedNcdType, setSelectedNcdType] = React.useState<NewCodeDefinitionType | null>(null);
<PageContentFontWrapper>
<p className="sw-mt-10">
<strong className="sw-body-md-highlight">
- {translate('new_code_definition.question')}
+ {isMultipleProjects
+ ? translate('new_code_definition.question.multiple_projects')
+ : translate('new_code_definition.question')}
</strong>
</p>
<div className="sw-mt-7 sw-ml-1" role="radiogroup">
</StyledGlobalSettingWrapper>
<RadioButton
- aria-label={translate('new_code_definition.specific_setting')}
+ aria-label={
+ isMultipleProjects
+ ? translate('new_code_definition.specific_setting.multiple_projects')
+ : translate('new_code_definition.specific_setting')
+ }
checked={Boolean(selectedNcdType && selectedNcdType !== NewCodeDefinitionType.Inherited)}
className="sw-mt-12 sw-font-semibold"
onCheck={() => handleNcdChanged(NewCodeDefinitionType.PreviousVersion)}
value="specific"
>
- {translate('new_code_definition.specific_setting')}
+ {isMultipleProjects
+ ? translate('new_code_definition.specific_setting.multiple_projects')
+ : translate('new_code_definition.specific_setting')}
</RadioButton>
</div>
#
#------------------------------------------------------------------------------
new_code_definition.question=Choose the baseline for new code for this project
+new_code_definition.question.multiple_projects=Choose the baseline for new code for those projects
new_code_definition.global_setting=Use the global setting
new_code_definition.specific_setting=Define a specific setting for this project
+new_code_definition.specific_setting.multiple_projects=Define a specific setting for your projects
new_code_definition.previous_version=Previous version
new_code_definition.previous_version.usecase=Recommended for projects following regular versions or releases.
onboarding.create_project.x_repository_created={count} {count, plural, one {repository} other {repositories}} will be created as a project on SonarQube
onboarding.create_project.new_code_definition.title=Set up project for Clean as You Code
+onboarding.create_x_project.new_code_definition.title=Set up {count, plural, one {project} other {# projects}} for Clean as You Code
onboarding.create_project.new_code_definition.description=The new code definition sets which part of your code will be considered new code. This helps you focus attention on the most recent changes to your project, enabling you to follow the Clean as You Code methodology. Learn more: {link}
onboarding.create_project.new_code_definition.description.link=Defining New Code
onboarding.create_project.new_code_definition.create_project=Create project
+onboarding.create_project.new_code_definition.create_x_projects=Create {count, plural, one {project} other {# projects}}
+onboarding.create_projects.new_code_definition.change_info=You can change this for each project individually at any time in the project administration.
onboarding.create_project.success=Congratulations! Your project has been created.