From ee27a13ee434d73973a16ae313d2d1447046d22a Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Thu, 10 Aug 2023 11:28:45 +0200 Subject: [PATCH] SONAR-20086 Migrate Bitbucket Cloud import page to the new UI --- .../src/components/input/InputSearch.tsx | 2 +- .../BitbucketCloudProjectCreate.tsx | 2 +- .../BitbucketCloudProjectCreateRender.tsx | 26 ++- .../BitbucketCloudSearchForm.tsx | 156 ++++++------------ .../Github/GitHubProjectCreateRenderer.tsx | 2 +- .../project/__tests__/BitbucketCloud-it.tsx | 31 ++-- .../main/js/apps/create/project/constants.ts | 2 + .../resources/org/sonar/l10n/core.properties | 1 + 8 files changed, 86 insertions(+), 136 deletions(-) diff --git a/server/sonar-web/design-system/src/components/input/InputSearch.tsx b/server/sonar-web/design-system/src/components/input/InputSearch.tsx index 25428652814..cb3eed1cbeb 100644 --- a/server/sonar-web/design-system/src/components/input/InputSearch.tsx +++ b/server/sonar-web/design-system/src/components/input/InputSearch.tsx @@ -145,7 +145,7 @@ export function InputSearch({ {children ?? ( { mounted = false; diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx index 770e8cac2ec..992f8046e4f 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx @@ -17,13 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { DeferredSpinner, LightPrimary, Title } from 'design-system'; 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 '../components/AlmSettingsInstanceDropdown'; -import CreateProjectPageHeader from '../components/CreateProjectPageHeader'; import PersonalAccessTokenForm from '../components/PersonalAccessTokenForm'; import WrongBindingCountAlert from '../components/WrongBindingCountAlert'; import BitbucketCloudSearchForm from './BitbucketCloudSearchForm'; @@ -66,19 +65,14 @@ export default function BitbucketCloudProjectCreateRenderer( return ( <> - - - {translate('onboarding.create_project.bitbucketcloud.title')} - - } - /> +
+ + {translate('onboarding.create_project.bitbucketcloud.title')} + + + {translate('onboarding.create_project.bitbucketcloud.subtitle')} + +
- {loading && } + {!loading && !selectedAlmInstance && ( 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 index 8b90691f348..206a2bcb082 100644 --- 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 @@ -17,22 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { FlagMessage, InputSearch, LightPrimary, Link } from 'design-system'; 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 ListFooter from '../../../../components/controls/ListFooter'; +import { translate } from '../../../../helpers/l10n'; +import { getBaseUrl } from '../../../../helpers/system'; +import { queryToSearch } from '../../../../helpers/urls'; import { BitbucketCloudRepository } from '../../../../types/alm-integration'; -import { ComponentQualifier } from '../../../../types/component'; -import { MetricType } from '../../../../types/metrics'; +import AlmRepoItem from '../components/AlmRepoItem'; +import { BITBUCKET_CLOUD_PROJECTS_PAGESIZE } from '../constants'; import { CreateProjectModes } from '../types'; export interface BitbucketCloudSearchFormProps { @@ -55,7 +49,7 @@ export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchForm if (repositories.length === 0 && searchQuery.length === 0 && !searching) { return ( - + - + ); } return ( -
- - -
+
+
+ +
{repositories.length === 0 ? ( -
{translate('no_results')}
+
+ {translate('no_results')} +
) : ( - - - {repositories.map((repository) => ( - - - - {repository.sqProjectKey ? ( - - ) : ( - - )} - - ))} - -
- - - {repository.sqProjectKey ? ( - - - {repository.name} - - ) : ( - repository.name - )} - - -
- - - {repository.projectKey} - - -
- - {translate('onboarding.create_project.bitbucketcloud.link')} - - - - - {translate('onboarding.create_project.repository_imported')} - - - -
+
+ {repositories.map((r) => ( + {r.name}} + secondaryTextNode={{r.projectKey}} + /> + ))} +
)} -
- {isLastPage && - translateWithParameters( - 'x_of_y_shown', - formatMeasure(repositories.length, MetricType.Integer, null), - formatMeasure(repositories.length, MetricType.Integer, null) - )} - {!isLastPage && ( - - )} - -
+ +
); } diff --git a/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx index 17a29443b71..69de3118fd3 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx @@ -76,12 +76,12 @@ function renderRepositoryList(props: GitHubProjectCreateRendererProps) {
-
{repositories.length === 0 ? ( 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 37558ec5f18..af4d30aa07c 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 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { act, screen, within } from '@testing-library/react'; +import { act, screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import * as React from 'react'; @@ -29,6 +29,7 @@ import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServi import { renderApp } from '../../../../helpers/testReactTestingUtils'; import { byLabelText, byRole, byText } from '../../../../helpers/testSelector'; import CreateProjectPage from '../CreateProjectPage'; +import { BITBUCKET_CLOUD_PROJECTS_PAGESIZE } from '../constants'; jest.mock('../../../../api/alm-integrations'); jest.mock('../../../../api/alm-settings'); @@ -148,7 +149,7 @@ it('should show import project feature when PAT is already set', async () => { projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 2/ }); const setupButton = within(projectItem).getByRole('button', { - name: 'onboarding.create_project.set_up', + name: 'onboarding.create_project.import', }); await user.click(setupButton); @@ -181,7 +182,7 @@ it('should show search filter when PAT is already set', async () => { expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( 'conf-bitbucketcloud-2', '', - 30, + BITBUCKET_CLOUD_PROJECTS_PAGESIZE, 1 ); @@ -194,7 +195,7 @@ it('should show search filter when PAT is already set', async () => { expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( 'conf-bitbucketcloud-2', 'search', - 30, + BITBUCKET_CLOUD_PROJECTS_PAGESIZE, 1 ); }); @@ -217,7 +218,10 @@ it('should show no result message when there are no projects', async () => { it('should have load more', async () => { const user = userEvent.setup(); - almIntegrationHandler.createRandomBitbucketCloudProjectsWithLoadMore(2, 4); + almIntegrationHandler.createRandomBitbucketCloudProjectsWithLoadMore( + BITBUCKET_CLOUD_PROJECTS_PAGESIZE, + BITBUCKET_CLOUD_PROJECTS_PAGESIZE + 1 + ); renderCreateProject(); expect(screen.getByText('onboarding.create_project.bitbucketcloud.title')).toBeInTheDocument(); @@ -227,23 +231,28 @@ it('should have load more', async () => { await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketcloud-2/]); }); - const loadMore = screen.getByRole('button', { name: 'show_more' }); - expect(loadMore).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'show_more' })).toBeInTheDocument(); /* * Next api call response will simulate reaching the last page so we can test the * loadmore button disapperance. */ - almIntegrationHandler.createRandomBitbucketCloudProjectsWithLoadMore(4, 4); - await user.click(loadMore); + almIntegrationHandler.createRandomBitbucketCloudProjectsWithLoadMore( + BITBUCKET_CLOUD_PROJECTS_PAGESIZE + 1, + BITBUCKET_CLOUD_PROJECTS_PAGESIZE + 1 + ); + await user.click(screen.getByRole('button', { name: 'show_more' })); expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( 'conf-bitbucketcloud-2', '', - 30, + BITBUCKET_CLOUD_PROJECTS_PAGESIZE, 2 ); - expect(loadMore).not.toBeInTheDocument(); + + await waitFor(() => { + expect(screen.queryByRole('button', { name: 'show_more' })).not.toBeInTheDocument(); + }); }); function renderCreateProject() { diff --git a/server/sonar-web/src/main/js/apps/create/project/constants.ts b/server/sonar-web/src/main/js/apps/create/project/constants.ts index 209b26dca3f..3a00eafc4a4 100644 --- a/server/sonar-web/src/main/js/apps/create/project/constants.ts +++ b/server/sonar-web/src/main/js/apps/create/project/constants.ts @@ -20,3 +20,5 @@ export const PROJECT_NAME_MAX_LEN = 255; export const DEFAULT_BBS_PAGE_SIZE = 25; + +export const BITBUCKET_CLOUD_PROJECTS_PAGESIZE = 20; 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 a702ea5c212..7dc5a3b10ab 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3960,6 +3960,7 @@ onboarding.create_project.azure.search_results_for_project_X=Search results for onboarding.create_project.azure.no_repositories=Could not fetch repositories for this project. Contact your system administrator, or {link}. onboarding.create_project.azure.no_results=No repositories match your search query. onboarding.create_project.bitbucketcloud.title=Bitbucket Cloud project onboarding +onboarding.create_project.bitbucketcloud.subtitle=Import projects from one of your Bitbucket Cloud workspaces onboarding.create_project.bitbucketcloud.no_projects=No projects could be fetched from Bitbucket. Contact your system administrator, or {link}. onboarding.create_project.bitbucketcloud.link=See on Bitbucket onboarding.create_project.github.title=GitHub project onboarding -- 2.39.5