aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud
diff options
context:
space:
mode:
authorShane Findley <shane.findley@sonarsource.com>2024-04-24 13:37:36 +0200
committerMatteo Mara <matteo.mara@sonarsource.com>2024-04-30 10:59:02 +0200
commit508bdf5808b401dd0745c0b01c4a8c5ad87bb307 (patch)
tree1fb10aefc1fd7b7affe7405372c9030162e17b69 /server/sonar-web/src/main/js/apps/create/project/BitbucketCloud
parent4b8b908e0e7aa880b6931ee2df3a88b95e9258a2 (diff)
downloadsonarqube-508bdf5808b401dd0745c0b01c4a8c5ad87bb307.tar.gz
sonarqube-508bdf5808b401dd0745c0b01c4a8c5ad87bb307.zip
SONAR-21824 Bitbucket monorepo import functionality (#11005)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/create/project/BitbucketCloud')
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx413
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx49
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx4
4 files changed, 242 insertions, 241 deletions
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx
index 4525e18b453..194fdc6ca8b 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx
@@ -17,6 +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 { Link, Spinner } from '@sonarsource/echoes-react';
import {
ButtonPrimary,
FlagErrorIcon,
@@ -24,17 +25,15 @@ import {
FormField,
InputField,
LightPrimary,
- Link,
- Spinner,
} from 'design-system';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from '../../../../helpers/l10n';
-import { AlmSettingsInstance } from '../../../../types/alm-settings';
+import { AlmInstanceBase } from '../../../../types/alm-settings';
import { usePersonalAccessToken } from '../usePersonalAccessToken';
interface Props {
- almSetting: AlmSettingsInstance;
+ almSetting: AlmInstanceBase;
resetPat: boolean;
onPersonalAccessTokenCreated: () => void;
}
@@ -43,7 +42,7 @@ export default function BitbucketCloudPersonalAccessTokenForm({
almSetting,
resetPat,
onPersonalAccessTokenCreated,
-}: Props) {
+}: Readonly<Props>) {
const {
username,
password,
@@ -59,12 +58,12 @@ export default function BitbucketCloudPersonalAccessTokenForm({
} = usePersonalAccessToken(almSetting, resetPat, onPersonalAccessTokenCreated);
if (checkingPat) {
- return <Spinner className="sw-ml-2" loading />;
+ return <Spinner className="sw-ml-2" isLoading />;
}
const isInvalid = validationFailed && !touched;
const canSubmit = Boolean(password) && Boolean(username);
- const submitButtonDiabled = isInvalid || submitting || !canSubmit;
+ const submitButtonDisabled = isInvalid || submitting || !canSubmit;
const errorMessage =
validationErrorMessage ?? translate('onboarding.create_project.pat_incorrect.bitbucket_cloud');
@@ -175,10 +174,10 @@ export default function BitbucketCloudPersonalAccessTokenForm({
</FlagMessage>
</div>
- <ButtonPrimary type="submit" disabled={submitButtonDiabled} className="sw-mb-6">
+ <ButtonPrimary type="submit" disabled={submitButtonDisabled} className="sw-mb-6">
{translate('save')}
</ButtonPrimary>
- <Spinner className="sw-ml-2" loading={submitting} />
+ <Spinner className="sw-ml-2" isLoading={submitting} />
</form>
);
}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
index 958473b2c7e..bb008260269 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
@@ -17,242 +17,215 @@
* 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 { LabelValueSelectOption } from 'design-system';
+import React, { useCallback, useMemo, useState } from 'react';
import { searchForBitbucketCloudRepositories } from '../../../../api/alm-integrations';
-import { Location, Router } from '../../../../components/hoc/withRouter';
+import { useLocation } from '../../../../components/hoc/withRouter';
import { BitbucketCloudRepository } from '../../../../types/alm-integration';
-import { AlmSettingsInstance } from '../../../../types/alm-settings';
-import { Paging } from '../../../../types/types';
+import { AlmKeys } from '../../../../types/alm-settings';
+import { DopSetting } from '../../../../types/dop-translation';
import { ImportProjectParam } from '../CreateProjectPage';
-import { BITBUCKET_CLOUD_PROJECTS_PAGESIZE } from '../constants';
+import { REPOSITORY_PAGE_SIZE } from '../constants';
+import MonorepoProjectCreate from '../monorepo/MonorepoProjectCreate';
import { CreateProjectModes } from '../types';
+import { useProjectCreate } from '../useProjectCreate';
+import { useProjectRepositorySearch } from '../useProjectRepositorySearch';
+import BitbucketCloudPersonalAccessTokenForm from './BitbucketCloudPersonalAccessTokenForm';
import BitbucketCloudProjectCreateRenderer from './BitbucketCloudProjectCreateRender';
interface Props {
- canAdmin: boolean;
- almInstances: AlmSettingsInstance[];
- loadingBindings: boolean;
- location: Location;
- router: Router;
+ dopSettings: DopSetting[];
+ isLoadingBindings: boolean;
onProjectSetupDone: (importProjects: ImportProjectParam) => void;
}
-interface State {
- isLastPage?: boolean;
- loading: boolean;
- loadingMore: boolean;
- projectsPaging: Omit<Paging, 'total'>;
- resetPat: boolean;
- repositories: BitbucketCloudRepository[];
- searching: boolean;
- searchQuery: string;
- selectedAlmInstance: AlmSettingsInstance;
- showPersonalAccessTokenForm: boolean;
-}
-
-export default class BitbucketCloudProjectCreate extends React.PureComponent<Props, State> {
- mounted = false;
-
- constructor(props: Props) {
- super(props);
- this.state = {
- // For now, we only handle a single instance. So we always use the first
- // one from the list.
- loading: false,
- loadingMore: false,
- resetPat: false,
- projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE },
- repositories: [],
- searching: false,
- searchQuery: '',
- selectedAlmInstance: props.almInstances[0],
- showPersonalAccessTokenForm: true,
- };
- }
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentDidUpdate(prevProps: Props) {
- if (prevProps.almInstances.length === 0 && this.props.almInstances.length > 0) {
- this.setState({ selectedAlmInstance: this.props.almInstances[0] }, () => {
- this.fetchData().catch(() => {
- /* noop */
- });
- });
- }
- }
+export default function BitbucketCloudProjectCreate(props: Readonly<Props>) {
+ const { dopSettings, isLoadingBindings, onProjectSetupDone } = props;
+
+ const [isLastPage, setIsLastPage] = useState<boolean>(true);
+ const [projectsPaging, setProjectsPaging] = useState<{ pageIndex: number; pageSize: number }>({
+ pageIndex: 1,
+ pageSize: REPOSITORY_PAGE_SIZE,
+ });
+
+ const {
+ handlePersonalAccessTokenCreated,
+ handleSelectRepository,
+ isInitialized,
+ isLoadingRepositories,
+ isLoadingMoreRepositories,
+ isMonorepoSetup,
+ onSelectedAlmInstanceChange,
+ onSelectDopSetting,
+ repositories,
+ resetLoading,
+ resetPersonalAccessToken,
+ searchQuery,
+ selectedDopSetting,
+ selectedRepository,
+ setIsInitialized,
+ setRepositories,
+ setResetPersonalAccessToken,
+ setSearchQuery,
+ setShowPersonalAccessTokenForm,
+ showPersonalAccessTokenForm,
+ } = useProjectCreate<BitbucketCloudRepository, undefined>(
+ AlmKeys.BitbucketCloud,
+ dopSettings,
+ ({ slug }) => slug,
+ REPOSITORY_PAGE_SIZE,
+ );
+
+ const location = useLocation();
+ const repositoryOptions = useMemo(() => repositories?.map(transformToOption), [repositories]);
+
+ const fetchRepositories = useCallback(
+ (_orgKey?: string, query = '', pageIndex = 1, more = false) => {
+ if (!selectedDopSetting || showPersonalAccessTokenForm) {
+ return Promise.resolve();
+ }
- handlePersonalAccessTokenCreated = () => {
- this.cleanUrl();
+ resetLoading(true, more);
- this.setState({ loading: true, showPersonalAccessTokenForm: false }, () => {
- this.fetchData()
- .then(() => this.setState({ loading: false }))
+ // eslint-disable-next-line local-rules/no-api-imports
+ return searchForBitbucketCloudRepositories(
+ selectedDopSetting.key,
+ query,
+ REPOSITORY_PAGE_SIZE,
+ pageIndex,
+ )
+ .then((result) => {
+ resetLoading(false, more);
+
+ if (result) {
+ setIsLastPage(result.isLastPage);
+ setIsInitialized(true);
+ }
+
+ if (result?.repositories) {
+ setRepositories(
+ more && repositories && repositories.length > 0
+ ? [...repositories, ...result.repositories]
+ : result.repositories,
+ );
+ }
+ })
.catch(() => {
- /* noop */
+ resetLoading(false, more);
+ setResetPersonalAccessToken(true);
+ setShowPersonalAccessTokenForm(true);
});
- });
- };
-
- cleanUrl = () => {
- const { location, router } = this.props;
- delete location.query.resetPat;
- router.replace(location);
- };
-
- async fetchData(more = false) {
- const {
- selectedAlmInstance,
- searchQuery,
- projectsPaging: { pageIndex, pageSize },
+ },
+ [
+ repositories,
+ resetLoading,
+ selectedDopSetting,
showPersonalAccessTokenForm,
- } = this.state;
- if (selectedAlmInstance && !showPersonalAccessTokenForm) {
- const { isLastPage, repositories } = await searchForBitbucketCloudRepositories(
- selectedAlmInstance.key,
- searchQuery,
- pageSize,
- pageIndex,
- ).catch(() => {
- this.handleError();
- return { isLastPage: undefined, repositories: undefined };
- });
- if (this.mounted && isLastPage !== undefined && repositories !== undefined) {
- if (more) {
- this.setState((state) => ({
- isLastPage,
- repositories: [...state.repositories, ...repositories],
- }));
- } else {
- this.setState({ isLastPage, repositories });
- }
+ setIsInitialized,
+ setIsLastPage,
+ setRepositories,
+ setResetPersonalAccessToken,
+ setShowPersonalAccessTokenForm,
+ ],
+ );
+
+ const handleLoadMore = useCallback(() => {
+ const page = projectsPaging.pageIndex + 1;
+ setProjectsPaging((paging) => ({
+ pageIndex: page,
+ pageSize: paging.pageSize,
+ }));
+
+ fetchRepositories(undefined, searchQuery, page, true);
+ }, [fetchRepositories, projectsPaging, searchQuery, setProjectsPaging]);
+
+ const handleImportRepository = useCallback(
+ (repositorySlug: string) => {
+ if (selectedDopSetting) {
+ onProjectSetupDone({
+ creationMode: CreateProjectModes.BitbucketCloud,
+ almSetting: selectedDopSetting.key,
+ monorepo: false,
+ projects: [{ repositorySlug }],
+ });
}
- }
- }
-
- handleError = () => {
- if (this.mounted) {
- this.setState({
- projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE },
- repositories: [],
- resetPat: true,
- showPersonalAccessTokenForm: true,
- });
- }
-
- return undefined;
- };
-
- handleSearch = (searchQuery: string) => {
- this.setState(
- {
- searching: true,
- projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE },
- searchQuery,
- },
- () => {
- this.fetchData().then(
- () => {
- if (this.mounted) {
- this.setState({ searching: false });
- }
- },
- () => {
- /* noop */
- },
- );
- },
- );
- };
-
- handleLoadMore = () => {
- this.setState(
- (state) => ({
- loadingMore: true,
- projectsPaging: {
- pageIndex: state.projectsPaging.pageIndex + 1,
- pageSize: state.projectsPaging.pageSize,
- },
- }),
- () => {
- this.fetchData(true).then(
- () => {
- if (this.mounted) {
- this.setState({ loadingMore: false });
+ },
+ [onProjectSetupDone, selectedDopSetting],
+ );
+
+ const { isSearching, onSearch } = useProjectRepositorySearch(
+ AlmKeys.BitbucketCloud,
+ fetchRepositories,
+ isInitialized,
+ selectedDopSetting,
+ undefined,
+ setSearchQuery,
+ showPersonalAccessTokenForm,
+ );
+
+ return isMonorepoSetup ? (
+ <MonorepoProjectCreate
+ dopSettings={dopSettings}
+ error={false}
+ loadingBindings={isLoadingBindings}
+ loadingOrganizations={false}
+ loadingRepositories={isLoadingRepositories}
+ onProjectSetupDone={onProjectSetupDone}
+ onSearchRepositories={onSearch}
+ onSelectDopSetting={onSelectDopSetting}
+ onSelectRepository={handleSelectRepository}
+ personalAccessTokenComponent={
+ !isLoadingRepositories &&
+ selectedDopSetting && (
+ <BitbucketCloudPersonalAccessTokenForm
+ almSetting={selectedDopSetting}
+ resetPat={resetPersonalAccessToken}
+ onPersonalAccessTokenCreated={handlePersonalAccessTokenCreated}
+ />
+ )
+ }
+ repositoryOptions={repositoryOptions}
+ repositorySearchQuery={searchQuery}
+ selectedDopSetting={selectedDopSetting}
+ selectedRepository={selectedRepository ? transformToOption(selectedRepository) : undefined}
+ showPersonalAccessToken={showPersonalAccessTokenForm || Boolean(location.query.resetPat)}
+ />
+ ) : (
+ <BitbucketCloudProjectCreateRenderer
+ isLastPage={isLastPage}
+ selectedAlmInstance={
+ selectedDopSetting
+ ? {
+ alm: selectedDopSetting.type,
+ key: selectedDopSetting.key,
+ url: selectedDopSetting.url,
}
- },
- () => {
- /* noop */
- },
- );
- },
- );
- };
-
- handleImport = (repositorySlug: string) => {
- const { selectedAlmInstance } = this.state;
-
- if (selectedAlmInstance) {
- this.props.onProjectSetupDone({
- creationMode: CreateProjectModes.BitbucketCloud,
- almSetting: selectedAlmInstance.key,
- monorepo: false,
- projects: [
- {
- repositorySlug,
- },
- ],
- });
- }
- };
-
- onSelectedAlmInstanceChange = (instance: AlmSettingsInstance) => {
- this.setState({
- selectedAlmInstance: instance,
- showPersonalAccessTokenForm: true,
- resetPat: false,
- searching: false,
- searchQuery: '',
- projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE },
- });
- };
+ : undefined
+ }
+ almInstances={dopSettings?.map((instance) => ({
+ alm: instance.type,
+ key: instance.key,
+ url: instance.url,
+ }))}
+ loadingMore={isLoadingMoreRepositories}
+ loading={isLoadingRepositories || isLoadingBindings}
+ onImport={handleImportRepository}
+ onLoadMore={handleLoadMore}
+ onPersonalAccessTokenCreated={handlePersonalAccessTokenCreated}
+ onSearch={onSearch}
+ onSelectedAlmInstanceChange={onSelectedAlmInstanceChange}
+ repositories={repositories}
+ searching={isSearching}
+ searchQuery={searchQuery}
+ resetPat={resetPersonalAccessToken || Boolean(location.query.resetPat)}
+ showPersonalAccessTokenForm={showPersonalAccessTokenForm || Boolean(location.query.resetPat)}
+ />
+ );
+}
- render() {
- const { canAdmin, loadingBindings, location, almInstances } = this.props;
- const {
- isLastPage = true,
- selectedAlmInstance,
- loading,
- loadingMore,
- repositories,
- showPersonalAccessTokenForm,
- resetPat,
- searching,
- searchQuery,
- } = this.state;
- return (
- <BitbucketCloudProjectCreateRenderer
- isLastPage={isLastPage}
- selectedAlmInstance={selectedAlmInstance}
- almInstances={almInstances}
- canAdmin={canAdmin}
- loadingMore={loadingMore}
- loading={loading || loadingBindings}
- onImport={this.handleImport}
- onLoadMore={this.handleLoadMore}
- onPersonalAccessTokenCreated={this.handlePersonalAccessTokenCreated}
- onSearch={this.handleSearch}
- onSelectedAlmInstanceChange={this.onSelectedAlmInstanceChange}
- repositories={repositories}
- searching={searching}
- searchQuery={searchQuery}
- resetPat={resetPat || Boolean(location.query.resetPat)}
- showPersonalAccessTokenForm={
- showPersonalAccessTokenForm || Boolean(location.query.resetPat)
- }
- />
- );
- }
+function transformToOption({
+ name,
+ slug,
+}: BitbucketCloudRepository): LabelValueSelectOption<string> {
+ return { value: slug, label: name };
}
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 5d36dd40b55..b38aaa8dadc 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,19 +17,25 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { LightPrimary, Spinner, Title } from 'design-system';
-import * as React from 'react';
+import { Link, Spinner } from '@sonarsource/echoes-react';
+import { LightPrimary, Title } from 'design-system';
+import React, { useContext } from 'react';
+import { FormattedMessage } from 'react-intl';
+import { AvailableFeaturesContext } from '../../../../app/components/available-features/AvailableFeaturesContext';
import { translate } from '../../../../helpers/l10n';
+import { queryToSearch } from '../../../../helpers/urls';
import { BitbucketCloudRepository } from '../../../../types/alm-integration';
import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
+import { Feature } from '../../../../types/features';
import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
+import { CreateProjectModes } from '../types';
import BitbucketCloudPersonalAccessTokenForm from './BitbucketCloudPersonalAccessTokenForm';
import BitbucketCloudSearchForm from './BitbucketCloudSearchForm';
export interface BitbucketCloudProjectCreateRendererProps {
+ almInstances: AlmSettingsInstance[];
isLastPage: boolean;
- canAdmin?: boolean;
loading: boolean;
loadingMore: boolean;
onImport: (repositorySlug: string) => void;
@@ -41,19 +47,21 @@ export interface BitbucketCloudProjectCreateRendererProps {
resetPat: boolean;
searching: boolean;
searchQuery: string;
- showPersonalAccessTokenForm: boolean;
- almInstances: AlmSettingsInstance[];
selectedAlmInstance?: AlmSettingsInstance;
+ showPersonalAccessTokenForm: boolean;
}
export default function BitbucketCloudProjectCreateRenderer(
props: Readonly<BitbucketCloudProjectCreateRendererProps>,
) {
+ const isMonorepoSupported = useContext(AvailableFeaturesContext).includes(
+ Feature.MonoRepositoryPullRequestDecoration,
+ );
+
const {
almInstances,
isLastPage,
selectedAlmInstance,
- canAdmin,
loading,
loadingMore,
repositories,
@@ -70,7 +78,28 @@ export default function BitbucketCloudProjectCreateRenderer(
{translate('onboarding.create_project.bitbucketcloud.title')}
</Title>
<LightPrimary className="sw-body-sm">
- {translate('onboarding.create_project.bitbucketcloud.subtitle')}
+ {isMonorepoSupported ? (
+ <FormattedMessage
+ id="onboarding.create_project.bitbucketcloud.subtitle.with_monorepo"
+ values={{
+ monorepoSetupLink: (
+ <Link
+ to={{
+ pathname: '/projects/create',
+ search: queryToSearch({
+ mode: CreateProjectModes.BitbucketCloud,
+ mono: true,
+ }),
+ }}
+ >
+ <FormattedMessage id="onboarding.create_project.subtitle_monorepo_setup_link" />
+ </Link>
+ ),
+ }}
+ />
+ ) : (
+ <FormattedMessage id="onboarding.create_project.bitbucketcloud.subtitle" />
+ )}
</LightPrimary>
</header>
@@ -81,10 +110,10 @@ export default function BitbucketCloudProjectCreateRenderer(
onChangeConfig={props.onSelectedAlmInstanceChange}
/>
- <Spinner loading={loading} />
+ <Spinner isLoading={loading} />
- {!loading && !selectedAlmInstance && (
- <WrongBindingCountAlert alm={AlmKeys.BitbucketCloud} canAdmin={!!canAdmin} />
+ {!loading && almInstances && almInstances.length === 0 && !selectedAlmInstance && (
+ <WrongBindingCountAlert alm={AlmKeys.BitbucketCloud} />
)}
{!loading &&
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 2b3fcd5c70e..35183531dd8 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
@@ -26,7 +26,7 @@ import { getBaseUrl } from '../../../../helpers/system';
import { queryToSearch } from '../../../../helpers/urls';
import { BitbucketCloudRepository } from '../../../../types/alm-integration';
import AlmRepoItem from '../components/AlmRepoItem';
-import { BITBUCKET_CLOUD_PROJECTS_PAGESIZE } from '../constants';
+import { REPOSITORY_PAGE_SIZE } from '../constants';
import { CreateProjectModes } from '../types';
export interface BitbucketCloudSearchFormProps {
@@ -112,7 +112,7 @@ export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchForm
count={repositories.length}
// we don't know the total, so only provide when we've reached the last page
total={isLastPage ? repositories.length : undefined}
- pageSize={BITBUCKET_CLOUD_PROJECTS_PAGESIZE}
+ pageSize={REPOSITORY_PAGE_SIZE}
loadMore={props.onLoadMore}
loading={loadingMore}
/>