@@ -295,6 +295,7 @@ export default class AllProjects extends React.PureComponent<Props, State> { | |||
{this.state.projects && ( | |||
<ProjectsList | |||
cardType={this.getView()} | |||
currentUser={this.props.currentUser} | |||
isFavorite={this.props.isFavorite} | |||
isFiltered={hasFilterParams(this.state.query)} | |||
organization={this.props.organization} |
@@ -18,12 +18,48 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import * as PropTypes from 'prop-types'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Button } from '../../../components/ui/buttons'; | |||
import { Organization, CurrentUser, isLoggedIn } from '../../../app/types'; | |||
import { isSonarCloud } from '../../../helpers/system'; | |||
export default function EmptyInstance() { | |||
return ( | |||
<div className="projects-empty-list"> | |||
<h3>{translate('projects.no_projects.empty_instance')}</h3> | |||
</div> | |||
); | |||
interface Props { | |||
organization?: Organization; | |||
currentUser: CurrentUser; | |||
} | |||
export default class EmptyInstance extends React.PureComponent<Props> { | |||
static contextTypes = { | |||
openProjectOnboarding: PropTypes.func | |||
}; | |||
render() { | |||
const { currentUser, organization } = this.props; | |||
const showNewProjectButton = isSonarCloud() | |||
? organization && organization.canProvisionProjects | |||
: isLoggedIn(currentUser); | |||
return ( | |||
<div className="projects-empty-list"> | |||
<h3> | |||
{showNewProjectButton | |||
? translate('projects.no_projects.empty_instance.new_project') | |||
: translate('projects.no_projects.empty_instance')} | |||
</h3> | |||
{showNewProjectButton && ( | |||
<div> | |||
<p className="big-spacer-top"> | |||
{translate('projects.no_projects.empty_instance.how_to_add_projects')} | |||
</p> | |||
<p className="big-spacer-top"> | |||
<Button onClick={this.context.openProjectOnboarding}> | |||
{translate('embed_docs.analyze_new_project')} | |||
</Button> | |||
</p> | |||
</div> | |||
)} | |||
</div> | |||
); | |||
} | |||
} |
@@ -28,10 +28,11 @@ import EmptyFavoriteSearch from './EmptyFavoriteSearch'; | |||
import EmptySearch from '../../../components/common/EmptySearch'; | |||
import { Project } from '../types'; | |||
import { Query } from '../query'; | |||
import { Organization } from '../../../app/types'; | |||
import { Organization, CurrentUser } from '../../../app/types'; | |||
interface Props { | |||
cardType?: string; | |||
currentUser: CurrentUser; | |||
isFavorite: boolean; | |||
isFiltered: boolean; | |||
organization: Organization | undefined; | |||
@@ -45,11 +46,15 @@ export default class ProjectsList extends React.PureComponent<Props> { | |||
}; | |||
renderNoProjects() { | |||
const { isFavorite, isFiltered, query } = this.props; | |||
const { currentUser, isFavorite, isFiltered, organization, query } = this.props; | |||
if (isFiltered) { | |||
return isFavorite ? <EmptyFavoriteSearch query={query} /> : <EmptySearch />; | |||
} | |||
return isFavorite ? <NoFavoriteProjects /> : <EmptyInstance />; | |||
return isFavorite ? ( | |||
<NoFavoriteProjects /> | |||
) : ( | |||
<EmptyInstance currentUser={currentUser} organization={organization} /> | |||
); | |||
} | |||
renderRow = ({ index, key, style }: ListRowProps) => { |
@@ -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. | |||
*/ | |||
/* eslint-disable import/order */ | |||
/* eslint-disable import/order, camelcase */ | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import AllProjects, { Props } from '../AllProjects'; |
@@ -20,7 +20,38 @@ | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import EmptyInstance from '../EmptyInstance'; | |||
import { isSonarCloud } from '../../../../helpers/system'; | |||
it('renders', () => { | |||
expect(shallow(<EmptyInstance />)).toMatchSnapshot(); | |||
jest.mock('../../../../helpers/system', () => ({ | |||
isSonarCloud: jest.fn() | |||
})); | |||
it('renders correctly for SQ', () => { | |||
(isSonarCloud as jest.Mock<any>).mockReturnValue(false); | |||
expect( | |||
shallow(<EmptyInstance currentUser={{ isLoggedIn: false }} organization={undefined} />) | |||
).toMatchSnapshot(); | |||
expect( | |||
shallow(<EmptyInstance currentUser={{ isLoggedIn: true }} organization={undefined} />) | |||
).toMatchSnapshot(); | |||
}); | |||
it('renders correctly for SC', () => { | |||
(isSonarCloud as jest.Mock<any>).mockReturnValue(true); | |||
expect( | |||
shallow( | |||
<EmptyInstance | |||
currentUser={{ isLoggedIn: false }} | |||
organization={{ key: 'foo', name: 'Foo' }} | |||
/> | |||
) | |||
).toMatchSnapshot(); | |||
expect( | |||
shallow( | |||
<EmptyInstance | |||
currentUser={{ isLoggedIn: false }} | |||
organization={{ canProvisionProjects: true, key: 'foo', name: 'Foo' }} | |||
/> | |||
) | |||
).toMatchSnapshot(); | |||
}); |
@@ -35,6 +35,7 @@ function shallowRender(props?: any) { | |||
return shallow( | |||
<ProjectsList | |||
cardType="overall" | |||
currentUser={{ isLoggedIn: true }} | |||
isFavorite={false} | |||
isFiltered={false} | |||
organization={undefined} |
@@ -84,6 +84,11 @@ exports[`renders 1`] = ` | |||
> | |||
<ProjectsList | |||
cardType="overall" | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
} | |||
} | |||
isFavorite={false} | |||
isFiltered={false} | |||
projects={ |
@@ -1,6 +1,6 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders 1`] = ` | |||
exports[`renders correctly for SC 1`] = ` | |||
<div | |||
className="projects-empty-list" | |||
> | |||
@@ -9,3 +9,61 @@ exports[`renders 1`] = ` | |||
</h3> | |||
</div> | |||
`; | |||
exports[`renders correctly for SC 2`] = ` | |||
<div | |||
className="projects-empty-list" | |||
> | |||
<h3> | |||
projects.no_projects.empty_instance.new_project | |||
</h3> | |||
<div> | |||
<p | |||
className="big-spacer-top" | |||
> | |||
projects.no_projects.empty_instance.how_to_add_projects | |||
</p> | |||
<p | |||
className="big-spacer-top" | |||
> | |||
<Button> | |||
embed_docs.analyze_new_project | |||
</Button> | |||
</p> | |||
</div> | |||
</div> | |||
`; | |||
exports[`renders correctly for SQ 1`] = ` | |||
<div | |||
className="projects-empty-list" | |||
> | |||
<h3> | |||
projects.no_projects.empty_instance | |||
</h3> | |||
</div> | |||
`; | |||
exports[`renders correctly for SQ 2`] = ` | |||
<div | |||
className="projects-empty-list" | |||
> | |||
<h3> | |||
projects.no_projects.empty_instance.new_project | |||
</h3> | |||
<div> | |||
<p | |||
className="big-spacer-top" | |||
> | |||
projects.no_projects.empty_instance.how_to_add_projects | |||
</p> | |||
<p | |||
className="big-spacer-top" | |||
> | |||
<Button> | |||
embed_docs.analyze_new_project | |||
</Button> | |||
</p> | |||
</div> | |||
</div> | |||
`; |
@@ -19,7 +19,13 @@ exports[`renders different types of "no projects" 1`] = ` | |||
<div | |||
className="projects-list" | |||
> | |||
<EmptyInstance /> | |||
<EmptyInstance | |||
currentUser={ | |||
Object { | |||
"isLoggedIn": true, | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
@@ -739,7 +739,9 @@ issue_bulk_change.no_match=There is no issue matching your filter selection | |||
projects.page=Projects | |||
projects._projects=projects | |||
projects.no_projects.empty_instance=Once you analyze some projects, they will show up here. | |||
projects.no_projects.empty_instance=There is no visible project yet. | |||
projects.no_projects.empty_instance.new_project=Once you analyze some projects, they will show up here. | |||
projects.no_projects.empty_instance.how_to_add_projects=Here is how you can analyse new projects | |||
projects.no_favorite_projects=You don't have any favorite projects yet. | |||
projects.no_favorite_projects.engagement=Discover and mark as favorites projects you are interested in to have a quick access to them. | |||
projects.no_favorite_projects.how_to_add_projects=Here is how to add projects to this page |