* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { groupBy } from 'lodash';
import * as React from 'react';
import {
checkPersonalAccessTokenIsValid,
projects?: AzureProject[];
repositories: Dict<AzureRepository[]>;
searching?: boolean;
- searchResults?: Dict<AzureRepository[]>;
+ searchResults?: AzureRepository[];
searchQuery?: string;
selectedRepository?: AzureRepository;
settings?: AlmSettingsInstance;
router.replace(location);
};
- handleOpenProject = async (projectKey: string) => {
+ handleOpenProject = async (projectName: string) => {
if (this.state.searchResults) {
return;
}
this.setState(({ loadingRepositories }) => ({
- loadingRepositories: { ...loadingRepositories, [projectKey]: true }
+ loadingRepositories: { ...loadingRepositories, [projectName]: true }
}));
- const projectRepos = await this.fetchAzureRepositories(projectKey);
+ const projectRepos = await this.fetchAzureRepositories(projectName);
this.setState(({ loadingRepositories, repositories }) => ({
- loadingRepositories: { ...loadingRepositories, [projectKey]: false },
- repositories: { ...repositories, [projectKey]: projectRepos }
+ loadingRepositories: { ...loadingRepositories, [projectName]: false },
+ repositories: { ...repositories, [projectName]: projectRepos }
}));
};
this.setState({ searching: true });
- const results: AzureRepository[] = await searchAzureRepositories(settings.key, searchQuery)
+ const searchResults: AzureRepository[] = await searchAzureRepositories(
+ settings.key,
+ searchQuery
+ )
.then(({ repositories }) => repositories)
.catch(() => []);
if (this.mounted) {
this.setState({
searching: false,
- searchResults: groupBy(results, 'projectName'),
+ searchResults,
searchQuery
});
}
projects?: AzureProject[];
repositories: Dict<AzureRepository[]>;
searching?: boolean;
- searchResults?: Dict<AzureRepository[]>;
+ searchResults?: AzureRepository[];
searchQuery?: string;
selectedRepository?: AzureRepository;
settings?: AlmSettingsInstance;
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { uniqBy } from 'lodash';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import ListFooter from '../../../components/controls/ListFooter';
import { Alert } from '../../../components/ui/Alert';
-import { translate } from '../../../helpers/l10n';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
import { queryToSearch } from '../../../helpers/urls';
import { AzureProject, AzureRepository } from '../../../types/alm-integration';
import { Dict } from '../../../types/types';
onSelectRepository: (repository: AzureRepository) => void;
projects?: AzureProject[];
repositories: Dict<AzureRepository[]>;
- searchResults?: Dict<AzureRepository[]>;
+ searchResults?: AzureRepository[];
searchQuery?: string;
selectedRepository?: AzureRepository;
}
const [page, setPage] = React.useState(1);
- const filteredProjects = searchResults
- ? projects.filter(p => searchResults[p.name] !== undefined)
- : projects;
+ if (searchResults && searchResults.length === 0) {
+ return (
+ <Alert className="spacer-top" variant="warning">
+ {translate('onboarding.create_project.azure.no_results')}
+ </Alert>
+ );
+ }
- if (filteredProjects.length === 0) {
+ if (projects.length === 0) {
return (
<Alert className="spacer-top" variant="warning">
- {searchResults ? (
- translate('onboarding.create_project.azure.no_results')
- ) : (
- <FormattedMessage
- defaultMessage={translate('onboarding.create_project.azure.no_projects')}
- id="onboarding.create_project.azure.no_projects"
- values={{
- link: (
- <Link
- to={{
- pathname: '/projects/create',
- search: queryToSearch({ mode: CreateProjectModes.AzureDevOps, resetPat: 1 })
- }}>
- {translate('onboarding.create_project.update_your_token')}
- </Link>
- )
- }}
- />
- )}
+ <FormattedMessage
+ defaultMessage={translate('onboarding.create_project.azure.no_projects')}
+ id="onboarding.create_project.azure.no_projects"
+ values={{
+ link: (
+ <Link
+ to={{
+ pathname: '/projects/create',
+ search: queryToSearch({ mode: CreateProjectModes.AzureDevOps, resetPat: 1 })
+ }}>
+ {translate('onboarding.create_project.update_your_token')}
+ </Link>
+ )
+ }}
+ />
</Alert>
);
}
+ let filteredProjects: AzureProject[];
+ if (searchResults !== undefined) {
+ filteredProjects = uniqBy(
+ searchResults.map(r => {
+ return (
+ projects.find(p => p.name === r.projectName) || {
+ name: r.projectName,
+ description: translateWithParameters(
+ 'onboarding.create_project.azure.search_results_for_project_X',
+ r.projectName
+ )
+ }
+ );
+ }),
+ 'name'
+ );
+ } else {
+ filteredProjects = projects;
+ }
+
const displayedProjects = filteredProjects.slice(0, page * PAGE_SIZE);
// Add a suffix to the key to force react to not reuse AzureProjectAccordions between
onOpen={props.onOpenProject}
onSelectRepository={props.onSelectRepository}
project={p}
- repositories={searchResults ? searchResults[p.name] : repositories[p.name]}
+ repositories={
+ searchResults
+ ? searchResults.filter(s => s.projectName === p.name)
+ : repositories[p.name]
+ }
selectedRepository={selectedRepository}
searchQuery={searchQuery}
startsOpen={searchResults !== undefined || i === 0}
expect(searchAzureRepositories).toBeCalledWith('foo', query);
await waitAndUpdate(wrapper);
expect(wrapper.state().searching).toBe(false);
- expect(wrapper.state().searchResults).toEqual({ [repositories[0].projectName]: repositories });
+ expect(wrapper.state().searchResults).toEqual(repositories);
expect(wrapper.state().searchQuery).toBe(query);
// Ignore opening a project when search results are displayed
mockAzureProject({ name: 'p2', description: 'p2' }),
mockAzureProject({ name: 'p3', description: 'p3' })
];
- const searchResults = {
- p2: [mockAzureRepository({ projectName: 'p2' })]
- };
+ const searchResults = [mockAzureRepository({ projectName: 'p2' })];
expect(shallowRender({ searchResults, projects })).toMatchSnapshot('default');
- expect(shallowRender({ searchResults: {}, projects })).toMatchSnapshot('empty');
+ expect(shallowRender({ searchResults: [], projects })).toMatchSnapshot('empty');
+ expect(
+ shallowRender({
+ searchResults: [
+ mockAzureRepository({ projectName: 'p2' }),
+ mockAzureRepository({ name: 'Unknown repository 1', projectName: 'u1' }),
+ mockAzureRepository({ name: 'Unknown repository 2', projectName: 'u2' })
+ ],
+ projects
+ })
+ ).toMatchSnapshot('search results belonging to unknown projects');
});
it('should handle pagination', () => {
onboarding.create_project.azure.no_results
</Alert>
`;
+
+exports[`should render search results correctly: search results belonging to unknown projects 1`] = `
+<div>
+ <AzureProjectAccordion
+ importing={false}
+ key="p2 - result"
+ loading={false}
+ onOpen={[MockFunction]}
+ onSelectRepository={[MockFunction]}
+ project={
+ Object {
+ "description": "p2",
+ "name": "p2",
+ }
+ }
+ repositories={
+ Array [
+ Object {
+ "name": "Azure repo 1",
+ "projectName": "p2",
+ },
+ ]
+ }
+ startsOpen={true}
+ />
+ <AzureProjectAccordion
+ importing={false}
+ key="u1 - result"
+ loading={false}
+ onOpen={[MockFunction]}
+ onSelectRepository={[MockFunction]}
+ project={
+ Object {
+ "description": "onboarding.create_project.azure.search_results_for_project_X.u1",
+ "name": "u1",
+ }
+ }
+ repositories={
+ Array [
+ Object {
+ "name": "Unknown repository 1",
+ "projectName": "u1",
+ },
+ ]
+ }
+ startsOpen={true}
+ />
+ <AzureProjectAccordion
+ importing={false}
+ key="u2 - result"
+ loading={false}
+ onOpen={[MockFunction]}
+ onSelectRepository={[MockFunction]}
+ project={
+ Object {
+ "description": "onboarding.create_project.azure.search_results_for_project_X.u2",
+ "name": "u2",
+ }
+ }
+ repositories={
+ Array [
+ Object {
+ "name": "Unknown repository 2",
+ "projectName": "u2",
+ },
+ ]
+ }
+ startsOpen={true}
+ />
+ <ListFooter
+ count={3}
+ loadMore={[Function]}
+ total={3}
+ />
+</div>
+`;
onboarding.create_project.set_up=Set up
onboarding.create_project.azure.title=Which Azure DevOps repository do you want to set up?
onboarding.create_project.azure.no_projects=No projects could be fetched from Azure DevOps. Contact your system administrator, or {link}.
+onboarding.create_project.azure.search_results_for_project_X=Search results for "{0}"
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=Which Bitbucket Cloud repository do you want to set up?