From 14205b07e4e521a837dd8a8177e2c8823d74a53d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Mon, 17 Dec 2018 15:26:40 +0100 Subject: [PATCH] SONARCLOUD-275 Add better scroll and repositories search on project import --- .../create/project/RemoteRepositories.tsx | 67 +++++++++++----- .../__tests__/RemoteRepositories-test.tsx | 15 ++++ .../RemoteRepositories-test.tsx.snap | 80 +++++++++++-------- .../src/main/js/apps/create/project/style.css | 9 +++ .../resources/org/sonar/l10n/core.properties | 2 + 5 files changed, 121 insertions(+), 52 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx b/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx index 60f2e637ff0..5032c975c56 100644 --- a/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/RemoteRepositories.tsx @@ -22,11 +22,12 @@ import * as classNames from 'classnames'; import AlmRepositoryItem from './AlmRepositoryItem'; import SetupProjectBox from './SetupProjectBox'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; +import SearchBox from '../../../components/controls/SearchBox'; import UpgradeOrganizationBox from '../components/UpgradeOrganizationBox'; +import { Alert } from '../../../components/ui/Alert'; import { getRepositories } from '../../../api/alm-integration'; import { isDefined } from '../../../helpers/types'; -import { translateWithParameters } from '../../../helpers/l10n'; -import { Alert } from '../../../components/ui/Alert'; +import { translateWithParameters, translate } from '../../../helpers/l10n'; interface Props { almApplication: T.AlmApplication; @@ -41,6 +42,7 @@ interface State { highlight: boolean; loading: boolean; repositories: T.AlmRepository[]; + search: string; selectedRepositories: SelectedRepositories; successfullyUpgraded: boolean; } @@ -51,6 +53,7 @@ export default class RemoteRepositories extends React.PureComponent { + this.setState({ search }); + }; + toggleRepository = (repository: T.AlmRepository) => { this.setState(({ selectedRepositories }) => ({ selectedRepositories: { @@ -128,16 +135,29 @@ export default class RemoteRepositories extends React.PureComponent Boolean(repository.private)); + const showSearchBox = repositories.length > 5; const showUpgradebox = !isPaidOrg && hasPrivateRepositories && organization.actions && organization.actions.admin; - + const filteredRepositories = repositories.filter( + repo => !search || repo.label.toLowerCase().includes(search.toLowerCase()) + ); return (
+ {showSearchBox && ( +
+ +
+ )} {this.state.successfullyUpgraded && ( {translateWithParameters( @@ -148,7 +168,14 @@ export default class RemoteRepositories extends React.PureComponent
    - {repositories.map(repo => ( + {filteredRepositories.length === 0 && ( +
  • + {showUpgradebox + ? translateWithParameters('no_results_for_x', search) + : translate('onboarding.create_project.no_repositories')} +
  • + )} + {filteredRepositories.map(repo => (
{organization && ( -
- selectedRepositories[r]) - .filter(isDefined)} - /> - {showUpgradebox && ( - +
+ selectedRepositories[r]) + .filter(isDefined)} /> - )} + {showUpgradebox && ( + + )} +
)}
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx index c37b1d1f4fb..62c7bae8d36 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/RemoteRepositories-test.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { times } from 'lodash'; import { shallow } from 'enzyme'; import RemoteRepositories from '../RemoteRepositories'; import { getRepositories } from '../../../../api/alm-integration'; @@ -92,6 +93,20 @@ it('should not display the organization upgrade box', () => { expect(wrapper.find('UpgradeOrganizationBox').exists()).toBe(false); }); +it('should display a search box to filter repositories', async () => { + (getRepositories as jest.Mock).mockResolvedValueOnce({ + repositories: times(6, i => ({ label: `Project ${i}`, installationKey: `key-${i}` })) + }); + + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + + expect(wrapper.find('SearchBox').exists()).toBe(true); + expect(wrapper.find('AlmRepositoryItem')).toHaveLength(6); + wrapper.find('SearchBox').prop('onChange')('3'); + expect(wrapper.find('AlmRepositoryItem')).toHaveLength(1); +}); + function shallowRender(props: Partial = {}) { return shallow( -
    +
      +
    • + onboarding.create_project.no_repositories +
    • +
    - + + selectedRepositories={Array []} + /> +
    `; @@ -99,24 +109,28 @@ exports[`should display the list of repositories 2`] = `
    - + + selectedRepositories={Array []} + /> +
    `; 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 b1481cd6d13..887b3f8f05a 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 @@ -57,6 +57,15 @@ box-shadow: none; } +.create-project-side-with-search { + margin-top: calc(4 * var(--gridSize)); +} + +.create-project-side-sticky { + position: sticky; + top: 68px; +} + .create-project-setup { display: flex; overflow: hidden; 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 909ad4dc927..4048b410921 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -939,6 +939,7 @@ search.search_by_login_or_name=Search by login or name... search.search_by_name=Search by name... search.search_by_name_or_key=Search by name or key... search.search_for_tags=Search for tags... +search.search_for_repositories=Search for repositories... search.search_for_rules=Search for rules... search.search_for_languages=Search for languages... search.search_for_cwe=Search for CWEs... @@ -2759,6 +2760,7 @@ onboarding.create_project.1_repository_created_as_public=1 repository will be cr onboarding.create_project.x_repository_created_as_public={0} repositories will be created as public projects on SonarCloud onboarding.create_project.1_repository_created_as_private=1 repository will be created as a private project on SonarCloud onboarding.create_project.x_repository_created_as_private={0} repositories will be created as private projects on SonarCloud +onboarding.create_project.no_repositories=No repositories found for this organization. onboarding.create_project.organization=Organization onboarding.create_project.project_key=Project key onboarding.create_project.project_key.description=Up to 400 characters. All letters, digits, dash, underscore, point or colon. -- 2.39.5