aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-web/src/main/js/api/mocks/NewCodePeriodsServiceMock.ts4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx)14
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/AzureProjectAccordion.tsx)24
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreate.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/AzureProjectCreate.tsx)12
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx)33
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectsList.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/AzureProjectsList.tsx)16
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx)10
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx)16
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx194
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloudSearchForm.tsx185
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketImportRepositoryForm.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketImportRepositoryForm.tsx)17
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectAccordion.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketProjectAccordion.tsx)20
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreate.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx)10
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx)20
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketRepositories.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketRepositories.tsx)6
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/BitbucketSearchResults.tsx)8
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreate.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/GitHubProjectCreate.tsx)12
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/GitHubProjectCreateRenderer.tsx)122
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreate.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreate.tsx)10
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx)18
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectSelectionForm.tsx173
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/GitlabProjectSelectionForm.tsx168
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.css26
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/Azure-it.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx24
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/components/AlmSettingsInstanceDropdown.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx)6
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/components/CreateProjectPageHeader.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/CreateProjectPageHeader.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/components/InstanceNewCodeDefinitionComplianceWarning.tsx95
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/components/PersonalAccessTokenForm.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx)18
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/components/WrongBindingCountAlert.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/WrongBindingCountAlert.tsx)12
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/manual/ManualProjectCreate.tsx (renamed from server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx)196
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/style.css5
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts20
-rw-r--r--server/sonar-web/src/main/js/helpers/periods.ts18
-rw-r--r--server/sonar-web/src/main/js/types/types.ts2
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties7
41 files changed, 868 insertions, 691 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/NewCodePeriodsServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/NewCodePeriodsServiceMock.ts
index 042d78ad54a..43a20156098 100644
--- a/server/sonar-web/src/main/js/api/mocks/NewCodePeriodsServiceMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/NewCodePeriodsServiceMock.ts
@@ -93,6 +93,10 @@ export default class NewCodePeriodsServiceMock {
return this.reply({ newCodePeriods: this.#listBranchesNewCode });
};
+ setNewCodePeriod = (newCodePeriod: NewCodePeriod) => {
+ this.#newCodePeriod = newCodePeriod;
+ };
+
reset = () => {
this.#newCodePeriod = cloneDeep(this.#defaultNewCodePeriod);
this.#listBranchesNewCode = cloneDeep(this.#defaultListBranchesNewCode);
diff --git a/server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx
index 24a81c34506..ba4c2a86cde 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx
@@ -20,13 +20,13 @@
import classNames from 'classnames';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import { SubmitButton } from '../../../components/controls/buttons';
-import ValidationInput from '../../../components/controls/ValidationInput';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { AlmSettingsInstance } from '../../../types/alm-settings';
+import Link from '../../../../components/common/Link';
+import ValidationInput from '../../../../components/controls/ValidationInput';
+import { SubmitButton } from '../../../../components/controls/buttons';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { AlmSettingsInstance } from '../../../../types/alm-settings';
export interface AzurePersonalAccessTokenFormProps {
almSetting: AlmSettingsInstance;
diff --git a/server/sonar-web/src/main/js/apps/create/project/AzureProjectAccordion.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx
index 0d96324e76b..bf202803792 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AzureProjectAccordion.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx
@@ -20,18 +20,18 @@
import classNames from 'classnames';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import { colors } from '../../../app/theme';
-import Link from '../../../components/common/Link';
-import BoxedGroupAccordion from '../../../components/controls/BoxedGroupAccordion';
-import ListFooter from '../../../components/controls/ListFooter';
-import Radio from '../../../components/controls/Radio';
-import CheckIcon from '../../../components/icons/CheckIcon';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { getProjectUrl, queryToSearch } from '../../../helpers/urls';
-import { AzureProject, AzureRepository } from '../../../types/alm-integration';
-import { CreateProjectModes } from './types';
+import { colors } from '../../../../app/theme';
+import Link from '../../../../components/common/Link';
+import BoxedGroupAccordion from '../../../../components/controls/BoxedGroupAccordion';
+import ListFooter from '../../../../components/controls/ListFooter';
+import Radio from '../../../../components/controls/Radio';
+import CheckIcon from '../../../../components/icons/CheckIcon';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { getProjectUrl, queryToSearch } from '../../../../helpers/urls';
+import { AzureProject, AzureRepository } from '../../../../types/alm-integration';
+import { CreateProjectModes } from '../types';
export interface AzureProjectAccordionProps {
importing: boolean;
diff --git a/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreate.tsx
index 94a98a331ed..8c8fb3fa673 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreate.tsx
@@ -25,13 +25,13 @@ import {
importAzureRepository,
searchAzureRepositories,
setAlmPersonalAccessToken,
-} from '../../../api/alm-integrations';
-import { Location, Router } from '../../../components/hoc/withRouter';
-import { AzureProject, AzureRepository } from '../../../types/alm-integration';
-import { AlmSettingsInstance } from '../../../types/alm-settings';
-import { Dict } from '../../../types/types';
+} from '../../../../api/alm-integrations';
+import { Location, Router } from '../../../../components/hoc/withRouter';
+import { AzureProject, AzureRepository } from '../../../../types/alm-integration';
+import { AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Dict } from '../../../../types/types';
+import { tokenExistedBefore } from '../utils';
import AzureCreateProjectRenderer from './AzureProjectCreateRenderer';
-import { tokenExistedBefore } from './utils';
interface Props {
canAdmin: boolean;
diff --git a/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx
index d3ad3e456b6..cbb051484bc 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx
@@ -19,23 +19,24 @@
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import { Button } from '../../../components/controls/buttons';
-import SearchBox from '../../../components/controls/SearchBox';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { getBaseUrl } from '../../../helpers/system';
-import { getGlobalSettingsUrl } from '../../../helpers/urls';
-import { AzureProject, AzureRepository } from '../../../types/alm-integration';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
-import { Dict } from '../../../types/types';
-import { ALM_INTEGRATION_CATEGORY } from '../../settings/constants';
-import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown';
+import Link from '../../../../components/common/Link';
+import SearchBox from '../../../../components/controls/SearchBox';
+import { Button } from '../../../../components/controls/buttons';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../helpers/system';
+import { getGlobalSettingsUrl } from '../../../../helpers/urls';
+import { AzureProject, AzureRepository } from '../../../../types/alm-integration';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Dict } from '../../../../types/types';
+import { ALM_INTEGRATION_CATEGORY } from '../../../settings/constants';
+import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
+import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
+import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
+import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
import AzurePersonalAccessTokenForm from './AzurePersonalAccessTokenForm';
import AzureProjectsList from './AzureProjectsList';
-import CreateProjectPageHeader from './CreateProjectPageHeader';
-import WrongBindingCountAlert from './WrongBindingCountAlert';
export interface AzureProjectCreateRendererProps {
canAdmin?: boolean;
@@ -164,6 +165,8 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend
</div>
) : (
<>
+ <InstanceNewCodeDefinitionComplianceWarning />
+
<div className="huge-spacer-bottom">
<SearchBox
onChange={props.onSearch}
diff --git a/server/sonar-web/src/main/js/apps/create/project/AzureProjectsList.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectsList.tsx
index 8fa25a3cfad..a393fe25c5c 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AzureProjectsList.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectsList.tsx
@@ -20,15 +20,15 @@
import { uniqBy } from 'lodash';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import ListFooter from '../../../components/controls/ListFooter';
-import { Alert } from '../../../components/ui/Alert';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { queryToSearch } from '../../../helpers/urls';
-import { AzureProject, AzureRepository } from '../../../types/alm-integration';
-import { Dict } from '../../../types/types';
+import Link from '../../../../components/common/Link';
+import ListFooter from '../../../../components/controls/ListFooter';
+import { Alert } from '../../../../components/ui/Alert';
+import { translate, translateWithParameters } from '../../../../helpers/l10n';
+import { queryToSearch } from '../../../../helpers/urls';
+import { AzureProject, AzureRepository } from '../../../../types/alm-integration';
+import { Dict } from '../../../../types/types';
+import { CreateProjectModes } from '../types';
import AzureProjectAccordion from './AzureProjectAccordion';
-import { CreateProjectModes } from './types';
export interface AzureProjectsListProps {
importing: boolean;
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
index 9f7fe3b8742..dd4bf7a1c96 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
@@ -21,11 +21,11 @@ import * as React from 'react';
import {
importBitbucketCloudRepository,
searchForBitbucketCloudRepositories,
-} from '../../../api/alm-integrations';
-import { Location, Router } from '../../../components/hoc/withRouter';
-import { BitbucketCloudRepository } from '../../../types/alm-integration';
-import { AlmSettingsInstance } from '../../../types/alm-settings';
-import { Paging } from '../../../types/types';
+} from '../../../../api/alm-integrations';
+import { Location, Router } from '../../../../components/hoc/withRouter';
+import { BitbucketCloudRepository } from '../../../../types/alm-integration';
+import { AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Paging } from '../../../../types/types';
import BitbucketCloudProjectCreateRenderer from './BitbucketCloudProjectCreateRender';
interface Props {
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx
index fcd4d48e483..28356e43449 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx
@@ -18,15 +18,15 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-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 { 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 '../components/AlmSettingsInstanceDropdown';
+import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
+import PersonalAccessTokenForm from '../components/PersonalAccessTokenForm';
+import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
import BitbucketCloudSearchForm from './BitbucketCloudSearchForm';
-import CreateProjectPageHeader from './CreateProjectPageHeader';
-import PersonalAccessTokenForm from './PersonalAccessTokenForm';
-import WrongBindingCountAlert from './WrongBindingCountAlert';
export interface BitbucketCloudProjectCreateRendererProps {
importingSlug?: string;
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx
new file mode 100644
index 00000000000..d52b70a176a
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx
@@ -0,0 +1,194 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import Link from '../../../../components/common/Link';
+import SearchBox from '../../../../components/controls/SearchBox';
+import Tooltip from '../../../../components/controls/Tooltip';
+import { Button } from '../../../../components/controls/buttons';
+import CheckIcon from '../../../../components/icons/CheckIcon';
+import QualifierIcon from '../../../../components/icons/QualifierIcon';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate, translateWithParameters } from '../../../../helpers/l10n';
+import { formatMeasure } from '../../../../helpers/measures';
+import { getProjectUrl, queryToSearch } from '../../../../helpers/urls';
+import { BitbucketCloudRepository } from '../../../../types/alm-integration';
+import { ComponentQualifier } from '../../../../types/component';
+import { MetricType } from '../../../../types/metrics';
+import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
+import { CreateProjectModes } from '../types';
+
+export interface BitbucketCloudSearchFormProps {
+ importingSlug?: string;
+ isLastPage: boolean;
+ loadingMore: boolean;
+ onImport: (repositorySlug: string) => void;
+ onLoadMore: () => void;
+ onSearch: (searchQuery: string) => void;
+ repositories?: BitbucketCloudRepository[];
+ searching: boolean;
+ searchQuery: string;
+}
+
+function getRepositoryUrl(workspace: string, slug: string) {
+ return `https://bitbucket.org/${workspace}/${slug}`;
+}
+
+export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchFormProps) {
+ const {
+ importingSlug,
+ isLastPage,
+ loadingMore,
+ repositories = [],
+ searching,
+ searchQuery,
+ } = props;
+
+ if (repositories.length === 0 && searchQuery.length === 0 && !searching) {
+ return (
+ <Alert className="spacer-top" variant="warning">
+ <FormattedMessage
+ defaultMessage={translate('onboarding.create_project.bitbucketcloud.no_projects')}
+ id="onboarding.create_project.bitbucketcloud.no_projects"
+ values={{
+ link: (
+ <Link
+ to={{
+ pathname: '/projects/create',
+ search: queryToSearch({ mode: CreateProjectModes.BitbucketCloud, resetPat: 1 }),
+ }}
+ >
+ {translate('onboarding.create_project.update_your_token')}
+ </Link>
+ ),
+ }}
+ />
+ </Alert>
+ );
+ }
+
+ return (
+ <>
+ <InstanceNewCodeDefinitionComplianceWarning />
+ <div className="boxed-group big-padded create-project-import">
+ <SearchBox
+ className="spacer"
+ loading={searching}
+ minLength={3}
+ onChange={props.onSearch}
+ placeholder={translate('onboarding.create_project.search_prompt')}
+ />
+
+ <hr />
+
+ {repositories.length === 0 ? (
+ <div className="padded">{translate('no_results')}</div>
+ ) : (
+ <table className="data zebra zebra-hover">
+ <tbody>
+ {repositories.map((repository) => (
+ <tr key={repository.uuid}>
+ <td>
+ <Tooltip overlay={repository.slug}>
+ <strong className="project-name display-inline-block text-ellipsis">
+ {repository.sqProjectKey ? (
+ <Link to={getProjectUrl(repository.sqProjectKey)}>
+ <QualifierIcon
+ className="spacer-right"
+ qualifier={ComponentQualifier.Project}
+ />
+ {repository.name}
+ </Link>
+ ) : (
+ repository.name
+ )}
+ </strong>
+ </Tooltip>
+ <br />
+ <Tooltip overlay={repository.projectKey}>
+ <span className="text-muted project-path display-inline-block text-ellipsis">
+ {repository.projectKey}
+ </span>
+ </Tooltip>
+ </td>
+ <td>
+ <Link
+ className="display-inline-flex-center big-spacer-right"
+ to={getRepositoryUrl(repository.workspace, repository.slug)}
+ target="_blank"
+ >
+ {translate('onboarding.create_project.bitbucketcloud.link')}
+ </Link>
+ </td>
+ {repository.sqProjectKey ? (
+ <td>
+ <span className="display-flex-center display-flex-justify-end already-set-up">
+ <CheckIcon className="little-spacer-right" size={12} />
+ {translate('onboarding.create_project.repository_imported')}
+ </span>
+ </td>
+ ) : (
+ <td className="text-right">
+ <Button
+ disabled={Boolean(importingSlug)}
+ onClick={() => {
+ props.onImport(repository.slug);
+ }}
+ >
+ {translate('onboarding.create_project.set_up')}
+ <DeferredSpinner
+ className="spacer-left"
+ loading={importingSlug === repository.slug}
+ />
+ </Button>
+ </td>
+ )}
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ )}
+ <footer className="spacer-top note text-center">
+ {isLastPage &&
+ translateWithParameters(
+ 'x_of_y_shown',
+ formatMeasure(repositories.length, MetricType.Integer, null),
+ formatMeasure(repositories.length, MetricType.Integer, null)
+ )}
+ {!isLastPage && (
+ <Button
+ className="spacer-left"
+ disabled={loadingMore}
+ data-test="show-more"
+ onClick={props.onLoadMore}
+ >
+ {translate('show_more')}
+ </Button>
+ )}
+ <DeferredSpinner
+ className="text-bottom spacer-left position-absolute"
+ loading={loadingMore}
+ />
+ </footer>
+ </div>
+ </>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudSearchForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudSearchForm.tsx
deleted file mode 100644
index 0e420e9864b..00000000000
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudSearchForm.tsx
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import { Button } from '../../../components/controls/buttons';
-import SearchBox from '../../../components/controls/SearchBox';
-import Tooltip from '../../../components/controls/Tooltip';
-import CheckIcon from '../../../components/icons/CheckIcon';
-import QualifierIcon from '../../../components/icons/QualifierIcon';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { formatMeasure } from '../../../helpers/measures';
-import { getProjectUrl, queryToSearch } from '../../../helpers/urls';
-import { BitbucketCloudRepository } from '../../../types/alm-integration';
-import { ComponentQualifier } from '../../../types/component';
-import { CreateProjectModes } from './types';
-
-export interface BitbucketCloudSearchFormProps {
- importingSlug?: string;
- isLastPage: boolean;
- loadingMore: boolean;
- onImport: (repositorySlug: string) => void;
- onLoadMore: () => void;
- onSearch: (searchQuery: string) => void;
- repositories?: BitbucketCloudRepository[];
- searching: boolean;
- searchQuery: string;
-}
-
-function getRepositoryUrl(workspace: string, slug: string) {
- return `https://bitbucket.org/${workspace}/${slug}`;
-}
-
-export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchFormProps) {
- const {
- importingSlug,
- isLastPage,
- loadingMore,
- repositories = [],
- searching,
- searchQuery,
- } = props;
-
- if (repositories.length === 0 && searchQuery.length === 0 && !searching) {
- return (
- <Alert className="spacer-top" variant="warning">
- <FormattedMessage
- defaultMessage={translate('onboarding.create_project.bitbucketcloud.no_projects')}
- id="onboarding.create_project.bitbucketcloud.no_projects"
- values={{
- link: (
- <Link
- to={{
- pathname: '/projects/create',
- search: queryToSearch({ mode: CreateProjectModes.BitbucketCloud, resetPat: 1 }),
- }}
- >
- {translate('onboarding.create_project.update_your_token')}
- </Link>
- ),
- }}
- />
- </Alert>
- );
- }
-
- return (
- <div className="boxed-group big-padded create-project-import">
- <SearchBox
- className="spacer"
- loading={searching}
- minLength={3}
- onChange={props.onSearch}
- placeholder={translate('onboarding.create_project.search_prompt')}
- />
-
- <hr />
-
- {repositories.length === 0 ? (
- <div className="padded">{translate('no_results')}</div>
- ) : (
- <table className="data zebra zebra-hover">
- <tbody>
- {repositories.map((repository) => (
- <tr key={repository.uuid}>
- <td>
- <Tooltip overlay={repository.slug}>
- <strong className="project-name display-inline-block text-ellipsis">
- {repository.sqProjectKey ? (
- <Link to={getProjectUrl(repository.sqProjectKey)}>
- <QualifierIcon
- className="spacer-right"
- qualifier={ComponentQualifier.Project}
- />
- {repository.name}
- </Link>
- ) : (
- repository.name
- )}
- </strong>
- </Tooltip>
- <br />
- <Tooltip overlay={repository.projectKey}>
- <span className="text-muted project-path display-inline-block text-ellipsis">
- {repository.projectKey}
- </span>
- </Tooltip>
- </td>
- <td>
- <Link
- className="display-inline-flex-center big-spacer-right"
- to={getRepositoryUrl(repository.workspace, repository.slug)}
- target="_blank"
- >
- {translate('onboarding.create_project.bitbucketcloud.link')}
- </Link>
- </td>
- {repository.sqProjectKey ? (
- <td>
- <span className="display-flex-center display-flex-justify-end already-set-up">
- <CheckIcon className="little-spacer-right" size={12} />
- {translate('onboarding.create_project.repository_imported')}
- </span>
- </td>
- ) : (
- <td className="text-right">
- <Button
- disabled={Boolean(importingSlug)}
- onClick={() => {
- props.onImport(repository.slug);
- }}
- >
- {translate('onboarding.create_project.set_up')}
- {importingSlug === repository.slug && (
- <DeferredSpinner className="spacer-left" />
- )}
- </Button>
- </td>
- )}
- </tr>
- ))}
- </tbody>
- </table>
- )}
- <footer className="spacer-top note text-center">
- {isLastPage &&
- translateWithParameters(
- 'x_of_y_shown',
- formatMeasure(repositories.length, 'INT', null),
- formatMeasure(repositories.length, 'INT', null)
- )}
- {!isLastPage && (
- <Button
- className="spacer-left"
- disabled={loadingMore}
- data-test="show-more"
- onClick={props.onLoadMore}
- >
- {translate('show_more')}
- </Button>
- )}
- {loadingMore && <DeferredSpinner className="text-bottom spacer-left position-absolute" />}
- </footer>
- </div>
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketImportRepositoryForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketImportRepositoryForm.tsx
index 6e00c7ece7c..8b22d219f30 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketImportRepositoryForm.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketImportRepositoryForm.tsx
@@ -19,19 +19,20 @@
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import SearchBox from '../../../components/controls/SearchBox';
-import { Alert } from '../../../components/ui/Alert';
-import { translate } from '../../../helpers/l10n';
-import { queryToSearch } from '../../../helpers/urls';
+import Link from '../../../../components/common/Link';
+import SearchBox from '../../../../components/controls/SearchBox';
+import { Alert } from '../../../../components/ui/Alert';
+import { translate } from '../../../../helpers/l10n';
+import { queryToSearch } from '../../../../helpers/urls';
import {
BitbucketProject,
BitbucketProjectRepositories,
BitbucketRepository,
-} from '../../../types/alm-integration';
+} from '../../../../types/alm-integration';
+import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
+import { CreateProjectModes } from '../types';
import BitbucketRepositories from './BitbucketRepositories';
import BitbucketSearchResults from './BitbucketSearchResults';
-import { CreateProjectModes } from './types';
export interface BitbucketImportRepositoryFormProps {
disableRepositories: boolean;
@@ -79,6 +80,8 @@ export default function BitbucketImportRepositoryForm(props: BitbucketImportRepo
return (
<div className="create-project-import-bbs">
+ <InstanceNewCodeDefinitionComplianceWarning />
+
<SearchBox
onChange={props.onSearch}
placeholder={translate('onboarding.create_project.search_repositories_by_name')}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectAccordion.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectAccordion.tsx
index 4eaa9943698..df14cad4b27 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectAccordion.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectAccordion.tsx
@@ -20,16 +20,16 @@
import classNames from 'classnames';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import { colors } from '../../../app/theme';
-import Link from '../../../components/common/Link';
-import BoxedGroupAccordion from '../../../components/controls/BoxedGroupAccordion';
-import Radio from '../../../components/controls/Radio';
-import CheckIcon from '../../../components/icons/CheckIcon';
-import { Alert } from '../../../components/ui/Alert';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { getProjectUrl, queryToSearch } from '../../../helpers/urls';
-import { BitbucketProject, BitbucketRepository } from '../../../types/alm-integration';
-import { CreateProjectModes } from './types';
+import { colors } from '../../../../app/theme';
+import Link from '../../../../components/common/Link';
+import BoxedGroupAccordion from '../../../../components/controls/BoxedGroupAccordion';
+import Radio from '../../../../components/controls/Radio';
+import CheckIcon from '../../../../components/icons/CheckIcon';
+import { Alert } from '../../../../components/ui/Alert';
+import { translate, translateWithParameters } from '../../../../helpers/l10n';
+import { getProjectUrl, queryToSearch } from '../../../../helpers/urls';
+import { BitbucketProject, BitbucketRepository } from '../../../../types/alm-integration';
+import { CreateProjectModes } from '../types';
export interface BitbucketProjectAccordionProps {
disableRepositories: boolean;
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreate.tsx
index 7719f31f5df..af60cb12b31 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreate.tsx
@@ -23,16 +23,16 @@ import {
getBitbucketServerRepositories,
importBitbucketServerProject,
searchForBitbucketServerRepositories,
-} from '../../../api/alm-integrations';
-import { Location, Router } from '../../../components/hoc/withRouter';
+} from '../../../../api/alm-integrations';
+import { Location, Router } from '../../../../components/hoc/withRouter';
import {
BitbucketProject,
BitbucketProjectRepositories,
BitbucketRepository,
-} from '../../../types/alm-integration';
-import { AlmSettingsInstance } from '../../../types/alm-settings';
+} from '../../../../types/alm-integration';
+import { AlmSettingsInstance } from '../../../../types/alm-settings';
+import { DEFAULT_BBS_PAGE_SIZE } from '../constants';
import BitbucketCreateProjectRenderer from './BitbucketProjectCreateRenderer';
-import { DEFAULT_BBS_PAGE_SIZE } from './constants';
interface Props {
canAdmin: boolean;
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx
index 2acbe01a87e..679c30c06e5 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx
@@ -18,21 +18,21 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { Button } from '../../../components/controls/buttons';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { getBaseUrl } from '../../../helpers/system';
+import { Button } from '../../../../components/controls/buttons';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../helpers/system';
import {
BitbucketProject,
BitbucketProjectRepositories,
BitbucketRepository,
-} from '../../../types/alm-integration';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
-import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown';
+} from '../../../../types/alm-integration';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
+import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
+import PersonalAccessTokenForm from '../components/PersonalAccessTokenForm';
+import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
import BitbucketImportRepositoryForm from './BitbucketImportRepositoryForm';
-import CreateProjectPageHeader from './CreateProjectPageHeader';
-import PersonalAccessTokenForm from './PersonalAccessTokenForm';
-import WrongBindingCountAlert from './WrongBindingCountAlert';
export interface BitbucketProjectCreateRendererProps {
selectedAlmInstance?: AlmSettingsInstance;
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketRepositories.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketRepositories.tsx
index 463050306bd..a7a225b510b 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketRepositories.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketRepositories.tsx
@@ -19,13 +19,13 @@
*/
import { uniq, without } from 'lodash';
import * as React from 'react';
-import { ButtonLink } from '../../../components/controls/buttons';
-import { translate } from '../../../helpers/l10n';
+import { ButtonLink } from '../../../../components/controls/buttons';
+import { translate } from '../../../../helpers/l10n';
import {
BitbucketProject,
BitbucketProjectRepositories,
BitbucketRepository,
-} from '../../../types/alm-integration';
+} from '../../../../types/alm-integration';
import BitbucketProjectAccordion from './BitbucketProjectAccordion';
export interface BitbucketRepositoriesProps {
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketSearchResults.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx
index 89870c0e954..93d71e08c68 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketSearchResults.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx
@@ -18,10 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { BitbucketProject, BitbucketRepository } from '../../../types/alm-integration';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { BitbucketProject, BitbucketRepository } from '../../../../types/alm-integration';
import BitbucketProjectAccordion from './BitbucketProjectAccordion';
export interface BitbucketSearchResultsProps {
diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
index 08fc333e5d7..1c92d7895a1 100644
--- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
@@ -32,13 +32,13 @@ import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
import { AppState } from '../../../types/appstate';
import { Feature } from '../../../types/features';
import AlmBindingDefinitionForm from '../../settings/components/almIntegration/AlmBindingDefinitionForm';
-import AzureProjectCreate from './AzureProjectCreate';
-import BitbucketCloudProjectCreate from './BitbucketCloudProjectCreate';
-import BitbucketProjectCreate from './BitbucketProjectCreate';
+import AzureProjectCreate from './Azure/AzureProjectCreate';
+import BitbucketCloudProjectCreate from './BitbucketCloud/BitbucketCloudProjectCreate';
+import BitbucketProjectCreate from './BitbucketServer/BitbucketProjectCreate';
import CreateProjectModeSelection from './CreateProjectModeSelection';
-import GitHubProjectCreate from './GitHubProjectCreate';
-import GitlabProjectCreate from './GitlabProjectCreate';
-import ManualProjectCreate from './ManualProjectCreate';
+import GitHubProjectCreate from './Github/GitHubProjectCreate';
+import GitlabProjectCreate from './Gitlab/GitlabProjectCreate';
+import ManualProjectCreate from './manual/ManualProjectCreate';
import './style.css';
import { CreateProjectModes } from './types';
diff --git a/server/sonar-web/src/main/js/apps/create/project/GitHubProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreate.tsx
index 0174873e06f..ec40e48c34c 100644
--- a/server/sonar-web/src/main/js/apps/create/project/GitHubProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreate.tsx
@@ -25,12 +25,12 @@ import {
getGithubOrganizations,
getGithubRepositories,
importGithubRepository,
-} from '../../../api/alm-integrations';
-import { Location, Router } from '../../../components/hoc/withRouter';
-import { getHostUrl } from '../../../helpers/urls';
-import { GithubOrganization, GithubRepository } from '../../../types/alm-integration';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
-import { Paging } from '../../../types/types';
+} from '../../../../api/alm-integrations';
+import { Location, Router } from '../../../../components/hoc/withRouter';
+import { getHostUrl } from '../../../../helpers/urls';
+import { GithubOrganization, GithubRepository } from '../../../../types/alm-integration';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Paging } from '../../../../types/types';
import GitHubProjectCreateRenderer from './GitHubProjectCreateRenderer';
interface Props {
diff --git a/server/sonar-web/src/main/js/apps/create/project/GitHubProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx
index 95b7fbbcf4a..ed2d238aad2 100644
--- a/server/sonar-web/src/main/js/apps/create/project/GitHubProjectCreateRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx
@@ -21,26 +21,27 @@
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import { colors } from '../../../app/theme';
-import Link from '../../../components/common/Link';
-import { Button } from '../../../components/controls/buttons';
-import ListFooter from '../../../components/controls/ListFooter';
-import Radio from '../../../components/controls/Radio';
-import SearchBox from '../../../components/controls/SearchBox';
-import Select, { LabelValueSelectOption } from '../../../components/controls/Select';
-import CheckIcon from '../../../components/icons/CheckIcon';
-import QualifierIcon from '../../../components/icons/QualifierIcon';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { getBaseUrl } from '../../../helpers/system';
-import { getProjectUrl } from '../../../helpers/urls';
-import { GithubOrganization, GithubRepository } from '../../../types/alm-integration';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
-import { ComponentQualifier } from '../../../types/component';
-import { Paging } from '../../../types/types';
-import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown';
-import CreateProjectPageHeader from './CreateProjectPageHeader';
+import { colors } from '../../../../app/theme';
+import Link from '../../../../components/common/Link';
+import ListFooter from '../../../../components/controls/ListFooter';
+import Radio from '../../../../components/controls/Radio';
+import SearchBox from '../../../../components/controls/SearchBox';
+import Select, { LabelValueSelectOption } from '../../../../components/controls/Select';
+import { Button } from '../../../../components/controls/buttons';
+import CheckIcon from '../../../../components/icons/CheckIcon';
+import QualifierIcon from '../../../../components/icons/QualifierIcon';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../helpers/system';
+import { getProjectUrl } from '../../../../helpers/urls';
+import { GithubOrganization, GithubRepository } from '../../../../types/alm-integration';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import { ComponentQualifier } from '../../../../types/component';
+import { Paging } from '../../../../types/types';
+import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
+import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
+import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
export interface GitHubProjectCreateRendererProps {
canAdmin: boolean;
@@ -255,44 +256,49 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe
)}
{!error && (
- <DeferredSpinner loading={loadingOrganizations}>
- <div className="form-field">
- <label htmlFor="github-choose-organization">
- {translate('onboarding.create_project.github.choose_organization')}
- </label>
- {organizations.length > 0 ? (
- <Select
- inputId="github-choose-organization"
- className="input-super-large"
- options={organizations.map(orgToOption)}
- onChange={({ value }: LabelValueSelectOption) => props.onSelectOrganization(value)}
- value={selectedOrganization ? orgToOption(selectedOrganization) : null}
- />
- ) : (
- !loadingOrganizations && (
- <Alert className="spacer-top" variant="error">
- {canAdmin ? (
- <FormattedMessage
- id="onboarding.create_project.github.no_orgs_admin"
- defaultMessage={translate('onboarding.create_project.github.no_orgs_admin')}
- values={{
- link: (
- <Link to="/admin/settings?category=almintegration">
- {translate(
- 'onboarding.create_project.github.warning.message_admin.link'
- )}
- </Link>
- ),
- }}
- />
- ) : (
- translate('onboarding.create_project.github.no_orgs')
- )}
- </Alert>
- )
- )}
- </div>
- </DeferredSpinner>
+ <>
+ <InstanceNewCodeDefinitionComplianceWarning />
+ <DeferredSpinner loading={loadingOrganizations}>
+ <div className="form-field">
+ <label htmlFor="github-choose-organization">
+ {translate('onboarding.create_project.github.choose_organization')}
+ </label>
+ {organizations.length > 0 ? (
+ <Select
+ inputId="github-choose-organization"
+ className="input-super-large"
+ options={organizations.map(orgToOption)}
+ onChange={({ value }: LabelValueSelectOption) =>
+ props.onSelectOrganization(value)
+ }
+ value={selectedOrganization ? orgToOption(selectedOrganization) : null}
+ />
+ ) : (
+ !loadingOrganizations && (
+ <Alert className="spacer-top" variant="error">
+ {canAdmin ? (
+ <FormattedMessage
+ id="onboarding.create_project.github.no_orgs_admin"
+ defaultMessage={translate('onboarding.create_project.github.no_orgs_admin')}
+ values={{
+ link: (
+ <Link to="/admin/settings?category=almintegration">
+ {translate(
+ 'onboarding.create_project.github.warning.message_admin.link'
+ )}
+ </Link>
+ ),
+ }}
+ />
+ ) : (
+ translate('onboarding.create_project.github.no_orgs')
+ )}
+ </Alert>
+ )
+ )}
+ </div>
+ </DeferredSpinner>
+ </>
)}
{renderRepositoryList(props)}
diff --git a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreate.tsx
index 7e4f7af64a3..45b7aa4e8d7 100644
--- a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreate.tsx
@@ -18,11 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { getGitlabProjects, importGitlabProject } from '../../../api/alm-integrations';
-import { Location, Router } from '../../../components/hoc/withRouter';
-import { GitlabProject } from '../../../types/alm-integration';
-import { AlmSettingsInstance } from '../../../types/alm-settings';
-import { Paging } from '../../../types/types';
+import { getGitlabProjects, importGitlabProject } from '../../../../api/alm-integrations';
+import { Location, Router } from '../../../../components/hoc/withRouter';
+import { GitlabProject } from '../../../../types/alm-integration';
+import { AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Paging } from '../../../../types/types';
import GitlabProjectCreateRenderer from './GitlabProjectCreateRenderer';
interface Props {
diff --git a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx
index a6f97855f14..366f5610d70 100644
--- a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx
@@ -18,16 +18,16 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { translate } from '../../../helpers/l10n';
-import { getBaseUrl } from '../../../helpers/system';
-import { GitlabProject } from '../../../types/alm-integration';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
-import { Paging } from '../../../types/types';
-import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown';
-import CreateProjectPageHeader from './CreateProjectPageHeader';
+import { translate } from '../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../helpers/system';
+import { GitlabProject } from '../../../../types/alm-integration';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Paging } from '../../../../types/types';
+import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
+import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
+import PersonalAccessTokenForm from '../components/PersonalAccessTokenForm';
+import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
import GitlabProjectSelectionForm from './GitlabProjectSelectionForm';
-import PersonalAccessTokenForm from './PersonalAccessTokenForm';
-import WrongBindingCountAlert from './WrongBindingCountAlert';
export interface GitlabProjectCreateRendererProps {
canAdmin?: boolean;
diff --git a/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectSelectionForm.tsx b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectSelectionForm.tsx
new file mode 100644
index 00000000000..56f3c8ebb39
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectSelectionForm.tsx
@@ -0,0 +1,173 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import Link from '../../../../components/common/Link';
+import ListFooter from '../../../../components/controls/ListFooter';
+import SearchBox from '../../../../components/controls/SearchBox';
+import Tooltip from '../../../../components/controls/Tooltip';
+import { Button } from '../../../../components/controls/buttons';
+import CheckIcon from '../../../../components/icons/CheckIcon';
+import QualifierIcon from '../../../../components/icons/QualifierIcon';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { getProjectUrl, queryToSearch } from '../../../../helpers/urls';
+import { GitlabProject } from '../../../../types/alm-integration';
+import { ComponentQualifier } from '../../../../types/component';
+import { Paging } from '../../../../types/types';
+import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
+import { CreateProjectModes } from '../types';
+
+export interface GitlabProjectSelectionFormProps {
+ importingGitlabProjectId?: string;
+ loadingMore: boolean;
+ onImport: (gitlabProjectId: string) => void;
+ onLoadMore: () => void;
+ onSearch: (searchQuery: string) => void;
+ projects?: GitlabProject[];
+ projectsPaging: Paging;
+ searching: boolean;
+ searchQuery: string;
+}
+
+export default function GitlabProjectSelectionForm(props: GitlabProjectSelectionFormProps) {
+ const {
+ importingGitlabProjectId,
+ loadingMore,
+ projects = [],
+ projectsPaging,
+ searching,
+ searchQuery,
+ } = props;
+
+ if (projects.length === 0 && searchQuery.length === 0 && !searching) {
+ return (
+ <Alert className="spacer-top" variant="warning">
+ <FormattedMessage
+ defaultMessage={translate('onboarding.create_project.gitlab.no_projects')}
+ id="onboarding.create_project.gitlab.no_projects"
+ values={{
+ link: (
+ <Link
+ to={{
+ pathname: '/projects/create',
+ search: queryToSearch({ mode: CreateProjectModes.GitLab, resetPat: 1 }),
+ }}
+ >
+ {translate('onboarding.create_project.update_your_token')}
+ </Link>
+ ),
+ }}
+ />
+ </Alert>
+ );
+ }
+
+ return (
+ <>
+ <InstanceNewCodeDefinitionComplianceWarning />
+ <div className="boxed-group big-padded create-project-import">
+ <SearchBox
+ className="spacer"
+ loading={searching}
+ minLength={3}
+ onChange={props.onSearch}
+ placeholder={translate('onboarding.create_project.search_prompt')}
+ />
+
+ <hr />
+
+ {projects.length === 0 ? (
+ <div className="padded">{translate('no_results')}</div>
+ ) : (
+ <table className="data zebra zebra-hover">
+ <tbody>
+ {projects.map((project) => (
+ <tr key={project.id}>
+ <td>
+ <Tooltip overlay={project.slug}>
+ <strong className="project-name display-inline-block text-ellipsis">
+ {project.sqProjectKey ? (
+ <Link to={getProjectUrl(project.sqProjectKey)}>
+ <QualifierIcon
+ className="spacer-right"
+ qualifier={ComponentQualifier.Project}
+ />
+ {project.sqProjectName}
+ </Link>
+ ) : (
+ project.name
+ )}
+ </strong>
+ </Tooltip>
+ <br />
+ <Tooltip overlay={project.pathSlug}>
+ <span className="text-muted project-path display-inline-block text-ellipsis">
+ {project.pathName}
+ </span>
+ </Tooltip>
+ </td>
+ <td>
+ <Link
+ className="display-inline-flex-center big-spacer-right"
+ to={project.url}
+ target="_blank"
+ >
+ {translate('onboarding.create_project.gitlab.link')}
+ </Link>
+ </td>
+ {project.sqProjectKey ? (
+ <td>
+ <span className="display-flex-center display-flex-justify-end already-set-up">
+ <CheckIcon className="little-spacer-right" size={12} />
+ {translate('onboarding.create_project.repository_imported')}
+ </span>
+ </td>
+ ) : (
+ <td className="text-right">
+ <Button
+ disabled={!!importingGitlabProjectId}
+ onClick={() => props.onImport(project.id)}
+ >
+ {translate('onboarding.create_project.set_up')}
+ <DeferredSpinner
+ className="spacer-left"
+ loading={importingGitlabProjectId === project.id}
+ />
+ </Button>
+ </td>
+ )}
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ )}
+ <ListFooter
+ count={projects.length}
+ loadMore={props.onLoadMore}
+ loading={loadingMore}
+ pageSize={projectsPaging.pageSize}
+ total={projectsPaging.total}
+ />
+ </div>
+ </>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectSelectionForm.tsx b/server/sonar-web/src/main/js/apps/create/project/GitlabProjectSelectionForm.tsx
deleted file mode 100644
index aad16aae6ec..00000000000
--- a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectSelectionForm.tsx
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import { Button } from '../../../components/controls/buttons';
-import ListFooter from '../../../components/controls/ListFooter';
-import SearchBox from '../../../components/controls/SearchBox';
-import Tooltip from '../../../components/controls/Tooltip';
-import CheckIcon from '../../../components/icons/CheckIcon';
-import QualifierIcon from '../../../components/icons/QualifierIcon';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { getProjectUrl, queryToSearch } from '../../../helpers/urls';
-import { GitlabProject } from '../../../types/alm-integration';
-import { ComponentQualifier } from '../../../types/component';
-import { Paging } from '../../../types/types';
-import { CreateProjectModes } from './types';
-
-export interface GitlabProjectSelectionFormProps {
- importingGitlabProjectId?: string;
- loadingMore: boolean;
- onImport: (gitlabProjectId: string) => void;
- onLoadMore: () => void;
- onSearch: (searchQuery: string) => void;
- projects?: GitlabProject[];
- projectsPaging: Paging;
- searching: boolean;
- searchQuery: string;
-}
-
-export default function GitlabProjectSelectionForm(props: GitlabProjectSelectionFormProps) {
- const {
- importingGitlabProjectId,
- loadingMore,
- projects = [],
- projectsPaging,
- searching,
- searchQuery,
- } = props;
-
- if (projects.length === 0 && searchQuery.length === 0 && !searching) {
- return (
- <Alert className="spacer-top" variant="warning">
- <FormattedMessage
- defaultMessage={translate('onboarding.create_project.gitlab.no_projects')}
- id="onboarding.create_project.gitlab.no_projects"
- values={{
- link: (
- <Link
- to={{
- pathname: '/projects/create',
- search: queryToSearch({ mode: CreateProjectModes.GitLab, resetPat: 1 }),
- }}
- >
- {translate('onboarding.create_project.update_your_token')}
- </Link>
- ),
- }}
- />
- </Alert>
- );
- }
-
- return (
- <div className="boxed-group big-padded create-project-import">
- <SearchBox
- className="spacer"
- loading={searching}
- minLength={3}
- onChange={props.onSearch}
- placeholder={translate('onboarding.create_project.search_prompt')}
- />
-
- <hr />
-
- {projects.length === 0 ? (
- <div className="padded">{translate('no_results')}</div>
- ) : (
- <table className="data zebra zebra-hover">
- <tbody>
- {projects.map((project) => (
- <tr key={project.id}>
- <td>
- <Tooltip overlay={project.slug}>
- <strong className="project-name display-inline-block text-ellipsis">
- {project.sqProjectKey ? (
- <Link to={getProjectUrl(project.sqProjectKey)}>
- <QualifierIcon
- className="spacer-right"
- qualifier={ComponentQualifier.Project}
- />
- {project.sqProjectName}
- </Link>
- ) : (
- project.name
- )}
- </strong>
- </Tooltip>
- <br />
- <Tooltip overlay={project.pathSlug}>
- <span className="text-muted project-path display-inline-block text-ellipsis">
- {project.pathName}
- </span>
- </Tooltip>
- </td>
- <td>
- <Link
- className="display-inline-flex-center big-spacer-right"
- to={project.url}
- target="_blank"
- >
- {translate('onboarding.create_project.gitlab.link')}
- </Link>
- </td>
- {project.sqProjectKey ? (
- <td>
- <span className="display-flex-center display-flex-justify-end already-set-up">
- <CheckIcon className="little-spacer-right" size={12} />
- {translate('onboarding.create_project.repository_imported')}
- </span>
- </td>
- ) : (
- <td className="text-right">
- <Button
- disabled={!!importingGitlabProjectId}
- onClick={() => props.onImport(project.id)}
- >
- {translate('onboarding.create_project.set_up')}
- {importingGitlabProjectId === project.id && (
- <DeferredSpinner className="spacer-left" />
- )}
- </Button>
- </td>
- )}
- </tr>
- ))}
- </tbody>
- </table>
- )}
- <ListFooter
- count={projects.length}
- loadMore={props.onLoadMore}
- loading={loadingMore}
- pageSize={projectsPaging.pageSize}
- total={projectsPaging.total}
- />
- </div>
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.css b/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.css
deleted file mode 100644
index 4ca8f2a4cc9..00000000000
--- a/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.css
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-.manual-project-create {
- max-width: 700px;
-}
-
-.manual-project-create .button {
- margin-top: var(--gridSize);
-}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/Azure-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/Azure-it.tsx
index 0ace653f9fe..a3e4a6b838f 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/Azure-it.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/Azure-it.tsx
@@ -26,6 +26,7 @@ import { byLabelText, byRole, byText } from 'testing-library-selector';
import { searchAzureRepositories } from '../../../../api/alm-integrations';
import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock';
import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock';
+import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage';
@@ -34,6 +35,7 @@ jest.mock('../../../../api/alm-settings');
let almIntegrationHandler: AlmIntegrationsServiceMock;
let almSettingsHandler: AlmSettingsServiceMock;
+let newCodePeriodHandler: NewCodePeriodsServiceMock;
const ui = {
azureCreateProjectButton: byText('onboarding.create_project.select_method.azure'),
@@ -46,12 +48,14 @@ const ui = {
beforeAll(() => {
almIntegrationHandler = new AlmIntegrationsServiceMock();
almSettingsHandler = new AlmSettingsServiceMock();
+ newCodePeriodHandler = new NewCodePeriodsServiceMock();
});
beforeEach(() => {
jest.clearAllMocks();
almIntegrationHandler.reset();
almSettingsHandler.reset();
+ newCodePeriodHandler.reset();
});
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx
index e8d1fd22e81..6c66849c475 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx
@@ -26,6 +26,7 @@ import { byLabelText, byRole, byText } from 'testing-library-selector';
import { searchForBitbucketServerRepositories } from '../../../../api/alm-integrations';
import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock';
import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock';
+import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage';
@@ -34,6 +35,7 @@ jest.mock('../../../../api/alm-settings');
let almIntegrationHandler: AlmIntegrationsServiceMock;
let almSettingsHandler: AlmSettingsServiceMock;
+let newCodePeriodHandler: NewCodePeriodsServiceMock;
const ui = {
bitbucketServerCreateProjectButton: byText('onboarding.create_project.select_method.bitbucket'),
@@ -46,12 +48,14 @@ const ui = {
beforeAll(() => {
almIntegrationHandler = new AlmIntegrationsServiceMock();
almSettingsHandler = new AlmSettingsServiceMock();
+ newCodePeriodHandler = new NewCodePeriodsServiceMock();
});
beforeEach(() => {
jest.clearAllMocks();
almIntegrationHandler.reset();
almSettingsHandler.reset();
+ newCodePeriodHandler.reset();
});
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx
index c82b35c2b86..c301a25e9df 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx
@@ -26,6 +26,7 @@ import { byLabelText, byRole, byText } from 'testing-library-selector';
import { searchForBitbucketCloudRepositories } from '../../../../api/alm-integrations';
import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock';
import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock';
+import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage';
@@ -34,6 +35,7 @@ jest.mock('../../../../api/alm-settings');
let almIntegrationHandler: AlmIntegrationsServiceMock;
let almSettingsHandler: AlmSettingsServiceMock;
+let newCodePeriodHandler: NewCodePeriodsServiceMock;
const ui = {
bitbucketCloudCreateProjectButton: byText(
@@ -48,12 +50,14 @@ const ui = {
beforeAll(() => {
almIntegrationHandler = new AlmIntegrationsServiceMock();
almSettingsHandler = new AlmSettingsServiceMock();
+ newCodePeriodHandler = new NewCodePeriodsServiceMock();
});
beforeEach(() => {
jest.clearAllMocks();
almIntegrationHandler.reset();
almSettingsHandler.reset();
+ newCodePeriodHandler.reset();
});
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx
index 9685d20f822..481a7db84ca 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx
@@ -26,6 +26,7 @@ import { byLabelText, byText } from 'testing-library-selector';
import { getGithubRepositories } from '../../../../api/alm-integrations';
import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock';
import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock';
+import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
import CreateProjectPage from '../CreateProjectPage';
@@ -36,6 +37,7 @@ const original = window.location;
let almIntegrationHandler: AlmIntegrationsServiceMock;
let almSettingsHandler: AlmSettingsServiceMock;
+let newCodePeriodHandler: NewCodePeriodsServiceMock;
const ui = {
githubCreateProjectButton: byText('onboarding.create_project.select_method.github'),
@@ -50,12 +52,14 @@ beforeAll(() => {
});
almIntegrationHandler = new AlmIntegrationsServiceMock();
almSettingsHandler = new AlmSettingsServiceMock();
+ newCodePeriodHandler = new NewCodePeriodsServiceMock();
});
beforeEach(() => {
jest.clearAllMocks();
almIntegrationHandler.reset();
almSettingsHandler.reset();
+ newCodePeriodHandler.reset();
});
afterAll(() => {
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx
index 88644cb4e44..0e71dbb86ff 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx
@@ -25,7 +25,10 @@ import { byLabelText, byRole, byText } from 'testing-library-selector';
import { getGitlabProjects } from '../../../../api/alm-integrations';
import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock';
import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock';
+import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
+import { mockNewCodePeriod } from '../../../../helpers/mocks/new-code-period';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
+import { NewCodePeriodSettingType } from '../../../../types/types';
import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage';
jest.mock('../../../../api/alm-integrations');
@@ -33,6 +36,7 @@ jest.mock('../../../../api/alm-settings');
let almIntegrationHandler: AlmIntegrationsServiceMock;
let almSettingsHandler: AlmSettingsServiceMock;
+let newCodePeriodHandler: NewCodePeriodsServiceMock;
const ui = {
gitlabCreateProjectButton: byText('onboarding.create_project.select_method.gitlab'),
@@ -46,12 +50,14 @@ const ui = {
beforeAll(() => {
almIntegrationHandler = new AlmIntegrationsServiceMock();
almSettingsHandler = new AlmSettingsServiceMock();
+ newCodePeriodHandler = new NewCodePeriodsServiceMock();
});
beforeEach(() => {
jest.clearAllMocks();
almIntegrationHandler.reset();
almSettingsHandler.reset();
+ newCodePeriodHandler.reset();
});
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
@@ -178,6 +184,24 @@ it('should show no result message when there are no projects', async () => {
);
});
+it('should display a warning if the instance default new code definition is not CaYC compliant', async () => {
+ const user = userEvent.setup();
+ newCodePeriodHandler.setNewCodePeriod(
+ mockNewCodePeriod({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '91' })
+ );
+ renderCreateProject();
+ await act(async () => {
+ await user.click(ui.gitlabCreateProjectButton.get());
+ await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]);
+ });
+
+ expect(screen.getByText('Gitlab project 1')).toBeInTheDocument();
+ expect(screen.getByText('Gitlab project 2')).toBeInTheDocument();
+ expect(screen.getByRole('alert')).toHaveTextContent(
+ 'onboarding.create_project.new_code_option.warning.title'
+ );
+});
+
function renderCreateProject(props: Partial<CreateProjectPageProps> = {}) {
renderApp('project/create', <CreateProjectPage {...props} />);
}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx
index 1ac0b03a7f6..98a05291a2a 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx
@@ -21,8 +21,9 @@ import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import * as React from 'react';
import { createProject, doesComponentExists } from '../../../../api/components';
+import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
-import ManualProjectCreate from '../ManualProjectCreate';
+import ManualProjectCreate from '../manual/ManualProjectCreate';
jest.mock('../../../../api/components', () => ({
createProject: jest.fn().mockResolvedValue({ project: { key: 'bar', name: 'Bar' } }),
@@ -35,8 +36,15 @@ jest.mock('../../../../api/settings', () => ({
getValue: jest.fn().mockResolvedValue({ value: 'main' }),
}));
+let newCodePeriodHandler: NewCodePeriodsServiceMock;
+
+beforeAll(() => {
+ newCodePeriodHandler = new NewCodePeriodsServiceMock();
+});
+
beforeEach(() => {
jest.clearAllMocks();
+ newCodePeriodHandler.reset();
});
it('should show branch information', async () => {
diff --git a/server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx b/server/sonar-web/src/main/js/apps/create/project/components/AlmSettingsInstanceDropdown.tsx
index 34d348c2c9f..b7c5c13c9c9 100644
--- a/server/sonar-web/src/main/js/apps/create/project/AlmSettingsInstanceDropdown.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/components/AlmSettingsInstanceDropdown.tsx
@@ -18,9 +18,9 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import AlmSettingsInstanceSelector from '../../../components/devops-platform/AlmSettingsInstanceSelector';
-import { hasMessage, translate, translateWithParameters } from '../../../helpers/l10n';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
+import AlmSettingsInstanceSelector from '../../../../components/devops-platform/AlmSettingsInstanceSelector';
+import { hasMessage, translate, translateWithParameters } from '../../../../helpers/l10n';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
export interface AlmSettingsInstanceDropdownProps {
almKey: AlmKeys;
diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageHeader.tsx b/server/sonar-web/src/main/js/apps/create/project/components/CreateProjectPageHeader.tsx
index f5d4517ff10..f5d4517ff10 100644
--- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPageHeader.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/components/CreateProjectPageHeader.tsx
diff --git a/server/sonar-web/src/main/js/apps/create/project/components/InstanceNewCodeDefinitionComplianceWarning.tsx b/server/sonar-web/src/main/js/apps/create/project/components/InstanceNewCodeDefinitionComplianceWarning.tsx
new file mode 100644
index 00000000000..7e0f2cc78c4
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/create/project/components/InstanceNewCodeDefinitionComplianceWarning.tsx
@@ -0,0 +1,95 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { getNewCodePeriod } from '../../../../api/newCodePeriod';
+import { AppStateContextProviderProps } from '../../../../app/components/app-state/AppStateContextProvider';
+import withAppStateContext from '../../../../app/components/app-state/withAppStateContext';
+import DocLink from '../../../../components/common/DocLink';
+import Link from '../../../../components/common/Link';
+import { Alert } from '../../../../components/ui/Alert';
+import { translate } from '../../../../helpers/l10n';
+import { isNewCodeDefinitionCompliant } from '../../../../helpers/periods';
+
+export type InstanceNewCodeDefinitionComplianceWarningProps = AppStateContextProviderProps;
+
+export function InstanceNewCodeDefinitionComplianceWarning({
+ appState: { canAdmin },
+}: InstanceNewCodeDefinitionComplianceWarningProps) {
+ const [isCompliant, setIsCompliant] = React.useState(true);
+
+ React.useEffect(() => {
+ async function fetchInstanceNCDOptionCompliance() {
+ const newCodeDefinition = await getNewCodePeriod();
+ setIsCompliant(isNewCodeDefinitionCompliant(newCodeDefinition));
+ }
+
+ fetchInstanceNCDOptionCompliance();
+ }, []);
+
+ if (isCompliant) {
+ return null;
+ }
+
+ return (
+ <Alert className="huge-spacer-bottom sw-max-w-[700px]" variant="warning">
+ <p className="sw-mb-2 sw-font-bold">
+ {translate('onboarding.create_project.new_code_option.warning.title')}
+ </p>
+ <p className="sw-mb-2">
+ <FormattedMessage
+ id="onboarding.create_project.new_code_option.warning.explanation"
+ defaultMessage={translate(
+ 'onboarding.create_project.new_code_option.warning.explanation'
+ )}
+ values={{
+ action: canAdmin ? (
+ <FormattedMessage
+ id="onboarding.create_project.new_code_option.warning.explanation.action.admin"
+ defaultMessage={translate(
+ 'onboarding.create_project.new_code_option.warning.explanation.action.admin'
+ )}
+ values={{
+ link: (
+ <Link to="/admin/settings?category=new_code_period">
+ {translate(
+ 'onboarding.create_project.new_code_option.warning.explanation.action.admin.link'
+ )}
+ </Link>
+ ),
+ }}
+ />
+ ) : (
+ translate('onboarding.create_project.new_code_option.warning.explanation.action')
+ ),
+ }}
+ />
+ </p>
+ <p>
+ {translate('learn_more')}:&nbsp;
+ <DocLink to="/project-administration/defining-new-code/">
+ {translate('onboarding.create_project.new_code_option.warning.learn_more.link')}
+ </DocLink>
+ </p>
+ </Alert>
+ );
+}
+
+export default withAppStateContext(InstanceNewCodeDefinitionComplianceWarning);
diff --git a/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/components/PersonalAccessTokenForm.tsx
index 589b8c72264..edba42d8ad4 100644
--- a/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/components/PersonalAccessTokenForm.tsx
@@ -23,15 +23,15 @@ import { FormattedMessage } from 'react-intl';
import {
checkPersonalAccessTokenIsValid,
setAlmPersonalAccessToken,
-} from '../../../api/alm-integrations';
-import { SubmitButton } from '../../../components/controls/buttons';
-import ValidationInput from '../../../components/controls/ValidationInput';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { translate } from '../../../helpers/l10n';
-import { getBaseUrl } from '../../../helpers/system';
-import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
-import { tokenExistedBefore } from './utils';
+} from '../../../../api/alm-integrations';
+import ValidationInput from '../../../../components/controls/ValidationInput';
+import { SubmitButton } from '../../../../components/controls/buttons';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { translate } from '../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../helpers/system';
+import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import { tokenExistedBefore } from '../utils';
interface Props {
almSetting: AlmSettingsInstance;
diff --git a/server/sonar-web/src/main/js/apps/create/project/WrongBindingCountAlert.tsx b/server/sonar-web/src/main/js/apps/create/project/components/WrongBindingCountAlert.tsx
index 7588b6cbf33..215cdf261c3 100644
--- a/server/sonar-web/src/main/js/apps/create/project/WrongBindingCountAlert.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/components/WrongBindingCountAlert.tsx
@@ -19,12 +19,12 @@
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import Link from '../../../components/common/Link';
-import { Alert } from '../../../components/ui/Alert';
-import { translate } from '../../../helpers/l10n';
-import { getGlobalSettingsUrl } from '../../../helpers/urls';
-import { AlmKeys } from '../../../types/alm-settings';
-import { ALM_INTEGRATION_CATEGORY } from '../../settings/constants';
+import Link from '../../../../components/common/Link';
+import { Alert } from '../../../../components/ui/Alert';
+import { translate } from '../../../../helpers/l10n';
+import { getGlobalSettingsUrl } from '../../../../helpers/urls';
+import { AlmKeys } from '../../../../types/alm-settings';
+import { ALM_INTEGRATION_CATEGORY } from '../../../settings/constants';
export interface WrongBindingCountAlertProps {
alm: AlmKeys;
diff --git a/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/manual/ManualProjectCreate.tsx
index 44b290ce91d..5a611d858af 100644
--- a/server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/manual/ManualProjectCreate.tsx
@@ -21,22 +21,22 @@ import classNames from 'classnames';
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 ValidationInput from '../../../components/controls/ValidationInput';
-import { SubmitButton } from '../../../components/controls/buttons';
-import { Alert } from '../../../components/ui/Alert';
-import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
-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 CreateProjectPageHeader from './CreateProjectPageHeader';
-import './ManualProjectCreate.css';
-import { PROJECT_NAME_MAX_LEN } from './constants';
+import { createProject, doesComponentExists } from '../../../../api/components';
+import { getValue } from '../../../../api/settings';
+import DocLink from '../../../../components/common/DocLink';
+import ProjectKeyInput from '../../../../components/common/ProjectKeyInput';
+import ValidationInput from '../../../../components/controls/ValidationInput';
+import { SubmitButton } from '../../../../components/controls/buttons';
+import { Alert } from '../../../../components/ui/Alert';
+import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import MandatoryFieldsExplanation from '../../../../components/ui/MandatoryFieldsExplanation';
+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 CreateProjectPageHeader from '../components/CreateProjectPageHeader';
+import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
+import { PROJECT_NAME_MAX_LEN } from '../constants';
interface Props {
branchesEnabled: boolean;
@@ -235,94 +235,90 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat
<>
<CreateProjectPageHeader title={translate('onboarding.create_project.setup_manually')} />
- <div className="create-project-manual">
- <div className="flex-1 huge-spacer-right">
- <form className="manual-project-create" onSubmit={this.handleFormSubmit}>
- <MandatoryFieldsExplanation className="big-spacer-bottom" />
+ <InstanceNewCodeDefinitionComplianceWarning />
- <ValidationInput
- className="form-field"
- description={translate('onboarding.create_project.display_name.description')}
- error={projectNameError}
- labelHtmlFor="project-name"
- isInvalid={projectNameIsInvalid}
- isValid={projectNameIsValid}
- label={translate('onboarding.create_project.display_name')}
- required={true}
- >
- <input
- className={classNames('input-super-large', {
- 'is-invalid': projectNameIsInvalid,
- 'is-valid': projectNameIsValid,
- })}
- id="project-name"
- maxLength={PROJECT_NAME_MAX_LEN}
- minLength={1}
- onChange={(e) => this.handleProjectNameChange(e.currentTarget.value, true)}
- type="text"
- value={projectName}
- autoFocus={true}
- />
- </ValidationInput>
- <ProjectKeyInput
- error={projectKeyError}
- label={translate('onboarding.create_project.project_key')}
- onProjectKeyChange={(e) => this.handleProjectKeyChange(e.currentTarget.value, true)}
- projectKey={projectKey}
- touched={touched}
- validating={validatingProjectKey}
- />
+ <form id="create-project-manual" onSubmit={this.handleFormSubmit}>
+ <MandatoryFieldsExplanation className="big-spacer-bottom" />
+
+ <ValidationInput
+ className="form-field"
+ description={translate('onboarding.create_project.display_name.description')}
+ error={projectNameError}
+ labelHtmlFor="project-name"
+ isInvalid={projectNameIsInvalid}
+ isValid={projectNameIsValid}
+ label={translate('onboarding.create_project.display_name')}
+ required={true}
+ >
+ <input
+ className={classNames('input-super-large', {
+ 'is-invalid': projectNameIsInvalid,
+ 'is-valid': projectNameIsValid,
+ })}
+ id="project-name"
+ maxLength={PROJECT_NAME_MAX_LEN}
+ minLength={1}
+ onChange={(e) => this.handleProjectNameChange(e.currentTarget.value, true)}
+ type="text"
+ value={projectName}
+ autoFocus={true}
+ />
+ </ValidationInput>
+ <ProjectKeyInput
+ error={projectKeyError}
+ label={translate('onboarding.create_project.project_key')}
+ onProjectKeyChange={(e) => this.handleProjectKeyChange(e.currentTarget.value, true)}
+ projectKey={projectKey}
+ touched={touched}
+ 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="/analyzing-source-code/branches/branch-analysis">
- {translate('learn_more')}
- </DocLink>
- ),
- }}
- />
- }
- error={mainBranchNameError}
- labelHtmlFor="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>
+ <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="/analyzing-source-code/branches/branch-analysis">
+ {translate('learn_more')}
+ </DocLink>
+ ),
+ }}
+ />
+ }
+ error={mainBranchNameError}
+ labelHtmlFor="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>
- <DeferredSpinner className="spacer-left" loading={submitting} />
- </form>
+ <SubmitButton disabled={!this.canSubmit(this.state) || submitting}>
+ {translate('set_up')}
+ </SubmitButton>
+ <DeferredSpinner className="spacer-left" loading={submitting} />
+ </form>
- {branchesEnabled && (
- <Alert variant="info" display="inline" className="big-spacer-top">
- {translate('onboarding.create_project.pr_decoration.information')}
- </Alert>
- )}
- </div>
- </div>
+ {branchesEnabled && (
+ <Alert variant="info" display="inline" className="big-spacer-top">
+ {translate('onboarding.create_project.pr_decoration.information')}
+ </Alert>
+ )}
</>
);
}
diff --git a/server/sonar-web/src/main/js/apps/create/project/style.css b/server/sonar-web/src/main/js/apps/create/project/style.css
index 1ee624a8394..c5355fd75d3 100644
--- a/server/sonar-web/src/main/js/apps/create/project/style.css
+++ b/server/sonar-web/src/main/js/apps/create/project/style.css
@@ -33,11 +33,6 @@
filter: grayscale(100%);
}
-.create-project-manual {
- display: flex !important;
- justify-content: space-between;
-}
-
.create-project-azdo-repo {
width: 410px;
min-height: 40px;
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts
index 59e62a8bf8d..73736fd7d7d 100644
--- a/server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts
+++ b/server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { NewCodePeriodSettingType } from '../../types/types';
-import { getPeriodLabel } from '../periods';
+import { NewCodePeriod, NewCodePeriodSettingType } from '../../types/types';
+import { getPeriodLabel, isNewCodeDefinitionCompliant } from '../periods';
import { mockPeriod } from '../testMocks';
const formatter = jest.fn((v) => v);
@@ -110,3 +110,19 @@ describe('getPeriodLabel', () => {
expect(formatter).toHaveBeenCalledTimes(1);
});
});
+
+describe('isNewCodeDefinitionCompliant', () => {
+ it.each([
+ [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '0' }, false],
+ [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '15' }, true],
+ [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '91' }, false],
+ [{ type: NewCodePeriodSettingType.PREVIOUS_VERSION }, true],
+ [{ type: NewCodePeriodSettingType.REFERENCE_BRANCH }, true],
+ [{ type: NewCodePeriodSettingType.SPECIFIC_ANALYSIS }, true],
+ ])(
+ 'should test for new code definition compliance properly',
+ (newCodePeriod: NewCodePeriod, result: boolean) => {
+ expect(isNewCodeDefinitionCompliant(newCodePeriod)).toEqual(result);
+ }
+ );
+});
diff --git a/server/sonar-web/src/main/js/helpers/periods.ts b/server/sonar-web/src/main/js/helpers/periods.ts
index 376a61c2a9c..2ffa7a88a80 100644
--- a/server/sonar-web/src/main/js/helpers/periods.ts
+++ b/server/sonar-web/src/main/js/helpers/periods.ts
@@ -20,7 +20,7 @@
import { parseDate } from '../helpers/dates';
import { translate, translateWithParameters } from '../helpers/l10n';
import { ApplicationPeriod } from '../types/application';
-import { NewCodePeriodSettingType, Period } from '../types/types';
+import { NewCodePeriod, NewCodePeriodSettingType, Period } from '../types/types';
export function getPeriodLabel(
period: Period | undefined,
@@ -68,3 +68,19 @@ export function isApplicationPeriod(
): period is ApplicationPeriod {
return (period as ApplicationPeriod).project !== undefined;
}
+
+const MIN_NUMBER_OF_DAYS = 1;
+const MAX_NUMBER_OF_DAYS = 90;
+
+export function isNewCodeDefinitionCompliant(newCodePeriod: NewCodePeriod) {
+ switch (newCodePeriod.type) {
+ case NewCodePeriodSettingType.NUMBER_OF_DAYS:
+ return (
+ newCodePeriod.value !== undefined &&
+ MIN_NUMBER_OF_DAYS <= +newCodePeriod.value &&
+ +newCodePeriod.value <= MAX_NUMBER_OF_DAYS
+ );
+ default:
+ return true;
+ }
+}
diff --git a/server/sonar-web/src/main/js/types/types.ts b/server/sonar-web/src/main/js/types/types.ts
index 94901ddc87a..0edbcf7a554 100644
--- a/server/sonar-web/src/main/js/types/types.ts
+++ b/server/sonar-web/src/main/js/types/types.ts
@@ -398,7 +398,7 @@ export interface MyProject {
}
export interface NewCodePeriod {
- type?: NewCodePeriodSettingType;
+ type: NewCodePeriodSettingType;
value?: string;
effectiveValue?: string;
inherited?: boolean;
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 26561038619..19f4a4e8f7f 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -3801,6 +3801,13 @@ onboarding.create_project.gitlab.title=Gitlab project onboarding
onboarding.create_project.gitlab.no_projects=No projects could be fetched from Gitlab. Contact your system administrator, or {link}.
onboarding.create_project.gitlab.link=See on GitLab
+onboarding.create_project.new_code_option.warning.title=Your global new code definition is not compliant with the Clean as You Code methodology
+onboarding.create_project.new_code_option.warning.explanation=New projects use the global new code definition by default. {action} so that new projects benefit from the Clean as You Code methodology by default.
+onboarding.create_project.new_code_option.warning.explanation.action=We recommend that you ask an administrator of this SonarQube instance to update the global new code definition
+onboarding.create_project.new_code_option.warning.explanation.action.admin=We recommend that you update the global new code definition under {link}
+onboarding.create_project.new_code_option.warning.explanation.action.admin.link=General Settings - New Code
+onboarding.create_project.new_code_option.warning.learn_more.link=Defining New Code
+
onboarding.token.header=Provide a token
onboarding.token.text=The token is used to identify you when an analysis is performed. If it has been compromised, you can revoke it at any point in time in your {link}.
onboarding.token.text.PROJECT_ANALYSIS_TOKEN=The project token is used to identify you when an analysis is performed. If it has been compromised, you can revoke it at any point in time in your {link}.