@@ -17,26 +17,30 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import PropTypes from 'prop-types'; | |||
import { withRouter } from 'react-router'; | |||
import * as React from 'react'; | |||
import * as PropTypes from 'prop-types'; | |||
import { connect } from 'react-redux'; | |||
import { getCurrentUser, getGlobalSettingValue } from '../../store/rootReducer'; | |||
import { CurrentUser, isLoggedIn } from '../types'; | |||
class Landing extends React.PureComponent { | |||
static propTypes = { | |||
currentUser: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]).isRequired | |||
interface Props { | |||
currentUser: CurrentUser; | |||
onSonarCloud: boolean; | |||
} | |||
class Landing extends React.PureComponent<Props> { | |||
static contextTypes = { | |||
router: PropTypes.object.isRequired | |||
}; | |||
componentDidMount() { | |||
const { currentUser, router, onSonarCloud } = this.props; | |||
if (currentUser.isLoggedIn) { | |||
router.replace('/projects'); | |||
} else if (onSonarCloud && onSonarCloud.value === 'true') { | |||
window.location = 'https://about.sonarcloud.io'; | |||
const { currentUser, onSonarCloud } = this.props; | |||
if (isLoggedIn(currentUser)) { | |||
this.context.router.replace('/projects'); | |||
} else if (onSonarCloud) { | |||
window.location.href = 'https://about.sonarcloud.io'; | |||
} else { | |||
router.replace('/about'); | |||
this.context.router.replace('/about'); | |||
} | |||
} | |||
@@ -45,9 +49,12 @@ class Landing extends React.PureComponent { | |||
} | |||
} | |||
const mapStateToProps = state => ({ | |||
currentUser: getCurrentUser(state), | |||
onSonarCloud: getGlobalSettingValue(state, 'sonar.sonarcloud.enabled') | |||
}); | |||
const mapStateToProps = (state: any) => { | |||
const onSonarCloudSetting = getGlobalSettingValue(state, 'sonar.sonarcloud.enabled'); | |||
return { | |||
currentUser: getCurrentUser(state), | |||
onSonarCloud: Boolean(onSonarCloudSetting && onSonarCloudSetting.value === 'true') | |||
}; | |||
}; | |||
export default connect(mapStateToProps)(withRouter(Landing)); | |||
export default connect<Props>(mapStateToProps)(Landing); |
@@ -32,7 +32,7 @@ type Props = { | |||
currentUser: { isLoggedIn: boolean }, | |||
onClose: () => void, | |||
onTutorialSelect: () => void, | |||
sonarCloud?: boolean | |||
onSonarCloud?: boolean | |||
}; | |||
*/ | |||
@@ -62,7 +62,7 @@ export default class GlobalHelp extends React.PureComponent { | |||
case 'shortcuts': | |||
return <ShortcutsHelp />; | |||
case 'links': | |||
return this.props.sonarCloud ? ( | |||
return this.props.onSonarCloud ? ( | |||
<LinksHelpSonarCloud onClose={this.props.onClose} /> | |||
) : ( | |||
<LinksHelp onClose={this.props.onClose} /> |
@@ -58,7 +58,7 @@ it('display special links page for SonarCloud', () => { | |||
currentUser={{ isLoggedIn: false }} | |||
onClose={jest.fn()} | |||
onTutorialSelect={jest.fn()} | |||
sonarCloud={true} | |||
onSonarCloud={true} | |||
/> | |||
); | |||
clickOnSection(wrapper, 'links'); |
@@ -22,6 +22,7 @@ import React from 'react'; | |||
import { connect } from 'react-redux'; | |||
import GlobalNavBranding from './GlobalNavBranding'; | |||
import GlobalNavMenu from './GlobalNavMenu'; | |||
import GlobalNavExplore from './GlobalNavExplore'; | |||
import GlobalNavUserContainer from './GlobalNavUserContainer'; | |||
import Search from '../../search/Search'; | |||
import GlobalHelp from '../../help/GlobalHelp'; | |||
@@ -38,8 +39,9 @@ import './GlobalNav.css'; | |||
type Props = { | |||
appState: { organizationsEnabled: boolean }, | |||
currentUser: { isLoggedIn: boolean, showOnboardingTutorial: boolean }, | |||
location: { pathname: string }, | |||
skipOnboarding: () => void, | |||
sonarCloud: boolean | |||
onSonarCloud: boolean | |||
}; | |||
*/ | |||
@@ -129,12 +131,14 @@ class GlobalNav extends React.PureComponent { | |||
<GlobalNavUserContainer {...this.props} /> | |||
</ul> | |||
<GlobalNavExplore location={this.props.location} onSonarCloud={this.props.onSonarCloud} /> | |||
{this.state.helpOpen && ( | |||
<GlobalHelp | |||
currentUser={this.props.currentUser} | |||
onClose={this.closeHelp} | |||
onTutorialSelect={this.openOnboardingTutorial} | |||
sonarCloud={this.props.sonarCloud} | |||
onSonarCloud={this.props.onSonarCloud} | |||
/> | |||
)} | |||
@@ -152,7 +156,7 @@ const mapStateToProps = state => { | |||
return { | |||
currentUser: getCurrentUser(state), | |||
appState: getAppState(state), | |||
sonarCloud: sonarCloudSetting != null && sonarCloudSetting.value === 'true' | |||
onSonarCloud: Boolean(sonarCloudSetting && sonarCloudSetting.value === 'true') | |||
}; | |||
}; | |||
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 { Link } from 'react-router'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
interface Props { | |||
location: { pathname: string }; | |||
onSonarCloud: boolean; | |||
} | |||
export default function GlobalNavExplore({ location, onSonarCloud }: Props) { | |||
if (!onSonarCloud) { | |||
return null; | |||
} | |||
const active = location.pathname.startsWith('explore'); | |||
return ( | |||
<ul className="global-navbar-menu spacer-right pull-right"> | |||
<li> | |||
<Link to="/explore/projects" className={active ? 'active' : undefined}> | |||
{translate('explore')} | |||
</Link> | |||
</li> | |||
</ul> | |||
); | |||
} |
@@ -20,6 +20,7 @@ | |||
import React from 'react'; | |||
import PropTypes from 'prop-types'; | |||
import { Link } from 'react-router'; | |||
import { isLoggedIn } from '../../../../app/types'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
import { getQualityGatesUrl } from '../../../../helpers/urls'; | |||
import { isMySet } from '../../../../apps/issues/utils'; | |||
@@ -31,7 +32,7 @@ export default class GlobalNavMenu extends React.PureComponent { | |||
location: PropTypes.shape({ | |||
pathname: PropTypes.string.isRequired | |||
}).isRequired, | |||
sonarCloud: PropTypes.bool | |||
onSonarCloud: PropTypes.bool | |||
}; | |||
static defaultProps = { | |||
@@ -44,10 +45,14 @@ export default class GlobalNavMenu extends React.PureComponent { | |||
} | |||
renderProjects() { | |||
if (this.props.onSonarCloud && !isLoggedIn(this.props.currentUser)) { | |||
return null; | |||
} | |||
return ( | |||
<li> | |||
<Link to="/projects" activeClassName="active"> | |||
{this.props.sonarCloud ? translate('my_projects') : translate('projects.page')} | |||
{this.props.onSonarCloud ? translate('my_projects') : translate('projects.page')} | |||
</Link> | |||
</li> | |||
); | |||
@@ -64,9 +69,13 @@ export default class GlobalNavMenu extends React.PureComponent { | |||
} | |||
renderIssuesLink() { | |||
if (this.props.onSonarCloud && !isLoggedIn(this.props.currentUser)) { | |||
return null; | |||
} | |||
const active = this.props.location.pathname === 'issues'; | |||
if (this.props.sonarCloud) { | |||
if (this.props.onSonarCloud) { | |||
return ( | |||
<li> | |||
<Link |
@@ -48,6 +48,9 @@ import componentMeasuresRoutes from '../../apps/component-measures/routes'; | |||
import customMeasuresRoutes from '../../apps/custom-measures/routes'; | |||
import groupsRoutes from '../../apps/groups/routes'; | |||
import Issues from '../../apps/issues/components/AppContainer'; | |||
import Explore from '../../apps/explore/Explore'; | |||
import ExploreIssues from '../../apps/explore/ExploreIssues'; | |||
import ExploreProjects from '../../apps/explore/ExploreProjects'; | |||
import IssuesPageSelector from '../../apps/issues/IssuesPageSelector'; | |||
import marketplaceRoutes from '../../apps/marketplace/routes'; | |||
import metricsRoutes from '../../apps/metrics/routes'; | |||
@@ -164,6 +167,10 @@ const startReactApp = () => { | |||
<Route path="account" childRoutes={accountRoutes} /> | |||
<Route path="coding_rules" childRoutes={codingRulesRoutes} /> | |||
<Route path="component" childRoutes={componentRoutes} /> | |||
<Route path="explore" component={Explore}> | |||
<Route path="issues" component={ExploreIssues} /> | |||
<Route path="projects" component={ExploreProjects} /> | |||
</Route> | |||
<Route | |||
path="extension/:pluginKey/:extensionKey" | |||
component={GlobalPageExtension} |
@@ -0,0 +1,57 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 { Link } from 'react-router'; | |||
import ContextNavBar from '../../components/nav/ContextNavBar'; | |||
import NavBarTabs from '../../components/nav/NavBarTabs'; | |||
import { translate } from '../../helpers/l10n'; | |||
interface Props { | |||
children: JSX.Element; | |||
} | |||
export default function Explore(props: Props) { | |||
return ( | |||
<div id="explore"> | |||
<ContextNavBar id="explore-navigation" height={65}> | |||
<div className="navbar-context-header"> | |||
<h1 className="display-inline-block">{translate('explore')}</h1> | |||
</div> | |||
<NavBarTabs> | |||
<li> | |||
<Link to="/explore/projects" activeClassName="active"> | |||
{translate('projects.page')} | |||
</Link> | |||
</li> | |||
<li> | |||
<Link | |||
to={{ pathname: '/explore/issues', query: { resolved: 'false' } }} | |||
activeClassName="active"> | |||
{translate('issues.page')} | |||
</Link> | |||
</li> | |||
</NavBarTabs> | |||
</ContextNavBar> | |||
{props.children} | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 AppContainer from '../issues/components/AppContainer'; | |||
import { RawQuery } from '../../helpers/query'; | |||
interface Props { | |||
location: { pathname: string; query: RawQuery }; | |||
} | |||
export default function ExploreIssues(props: Props) { | |||
return <AppContainer myIssues={false} {...props} />; | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 AllProjectsContainer from '../projects/components/AllProjectsContainer'; | |||
import { RawQuery } from '../../helpers/query'; | |||
interface Props { | |||
location: { pathname: string; query: RawQuery }; | |||
} | |||
export default function ExploreProjects(props: Props) { | |||
return <AllProjectsContainer isFavorite={false} {...props} />; | |||
} |
@@ -22,15 +22,20 @@ import { connect } from 'react-redux'; | |||
import AppContainer from './components/AppContainer'; | |||
import { CurrentUser, isLoggedIn } from '../../app/types'; | |||
import { getCurrentUser, getGlobalSettingValue } from '../../store/rootReducer'; | |||
import { RawQuery } from '../../helpers/query'; | |||
interface StateProps { | |||
currentUser: CurrentUser; | |||
onSonarCloud: boolean; | |||
} | |||
function IssuesPage({ currentUser, onSonarCloud, ...props }: StateProps) { | |||
interface Props extends StateProps { | |||
location: { pathname: string; query: RawQuery }; | |||
} | |||
function IssuesPage({ currentUser, location, onSonarCloud }: Props) { | |||
const myIssues = (isLoggedIn(currentUser) && onSonarCloud) || undefined; | |||
return <AppContainer myIssues={myIssues} {...props} />; | |||
return <AppContainer location={location} myIssues={myIssues} />; | |||
} | |||
const stateToProps = (state: any) => { |
@@ -31,6 +31,7 @@ import IssuesList from './IssuesList'; | |||
import ComponentBreadcrumbs from './ComponentBreadcrumbs'; | |||
import IssuesSourceViewer from './IssuesSourceViewer'; | |||
import BulkChangeModal from './BulkChangeModal'; | |||
import NoMyIssues from './NoMyIssues'; | |||
import ConciseIssuesList from '../conciseIssuesList/ConciseIssuesList'; | |||
import ConciseIssuesListHeader from '../conciseIssuesList/ConciseIssuesListHeader'; | |||
import * as actions from '../actions'; | |||
@@ -868,7 +869,8 @@ export default class App extends React.PureComponent { | |||
<ListFooter total={paging.total} count={issues.length} loadMore={this.fetchMoreIssues} /> | |||
)} | |||
{paging.total === 0 && <EmptySearch />} | |||
{paging.total === 0 && | |||
(this.state.myIssues && !this.isFiltered() ? <NoMyIssues /> : <EmptySearch />)} | |||
</div> | |||
); | |||
} |
@@ -88,6 +88,7 @@ interface DispatchProps { | |||
const mapDispatchToProps = { fetchIssues: fetchIssues as any } as DispatchProps; | |||
interface OwnProps { | |||
location: { pathname: string; query: RawQuery }; | |||
myIssues?: boolean; | |||
} | |||
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 { translate } from '../../../helpers/l10n'; | |||
import '../../../components/common/EmptySearch.css'; | |||
export default function NoMyIssues() { | |||
return ( | |||
<div className="empty-search"> | |||
<h3>{translate('issues.no_my_issues')}</h3> | |||
</div> | |||
); | |||
} |
@@ -20,12 +20,14 @@ | |||
import * as React from 'react'; | |||
import * as PropTypes from 'prop-types'; | |||
import Helmet from 'react-helmet'; | |||
import { omitBy } from 'lodash'; | |||
import PageHeader from './PageHeader'; | |||
import ProjectsList from './ProjectsList'; | |||
import PageSidebar from './PageSidebar'; | |||
import Visualizations from '../visualizations/Visualizations'; | |||
import { CurrentUser, isLoggedIn } from '../../../app/types'; | |||
import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; | |||
import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; | |||
import ListFooter from '../../../components/controls/ListFooter'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import * as storage from '../../../helpers/storage'; | |||
@@ -38,7 +40,7 @@ import { parseUrlQuery, Query } from '../query'; | |||
export interface Props { | |||
currentUser: CurrentUser; | |||
isFavorite: boolean; | |||
location: { pathname: string; query: { [x: string]: string } }; | |||
location: { pathname: string; query: RawQuery }; | |||
onSonarCloud: boolean; | |||
organization?: { key: string }; | |||
organizationsEnabled: boolean; | |||
@@ -224,35 +226,35 @@ export default class AllProjects extends React.PureComponent<Props, State> { | |||
} | |||
updateLocationQuery = (newQuery: RawQuery) => { | |||
this.context.router.push({ | |||
pathname: this.props.location.pathname, | |||
query: { | |||
...this.props.location.query, | |||
...newQuery | |||
} | |||
}); | |||
const query = omitBy({ ...this.props.location.query, ...newQuery }, x => !x); | |||
this.context.router.push({ pathname: this.props.location.pathname, query }); | |||
}; | |||
handleClearAll = () => { | |||
this.context.router.push({ pathname: this.props.location.pathname }); | |||
}; | |||
renderSide = () => ( | |||
<div className="layout-page-side-outer"> | |||
<div | |||
className="layout-page-side projects-page-side" | |||
style={{ top: this.props.organization ? 95 : 30 }}> | |||
<div className="layout-page-side-inner"> | |||
<div className="layout-page-filters"> | |||
<PageSidebar | |||
facets={this.state.facets} | |||
isFavorite={this.props.isFavorite} | |||
organization={this.props.organization} | |||
query={this.state.query} | |||
showFavoriteFilter={!this.props.onSonarCloud} | |||
view={this.getView()} | |||
visualization={this.getVisualization()} | |||
/> | |||
<ScreenPositionHelper className="layout-page-side-outer"> | |||
{({ top }) => ( | |||
<div className="layout-page-side projects-page-side" style={{ top }}> | |||
<div className="layout-page-side-inner"> | |||
<div className="layout-page-filters"> | |||
<PageSidebar | |||
facets={this.state.facets} | |||
onClearAll={this.handleClearAll} | |||
onQueryChange={this.updateLocationQuery} | |||
organization={this.props.organization} | |||
query={this.state.query} | |||
showFavoriteFilter={!this.props.onSonarCloud} | |||
view={this.getView()} | |||
visualization={this.getVisualization()} | |||
/> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
)} | |||
</ScreenPositionHelper> | |||
); | |||
renderHeader = () => ( | |||
@@ -261,9 +263,9 @@ export default class AllProjects extends React.PureComponent<Props, State> { | |||
<div className="layout-page-main-inner"> | |||
<PageHeader | |||
currentUser={this.props.currentUser} | |||
isFavorite={this.props.isFavorite} | |||
loading={this.state.loading} | |||
onPerspectiveChange={this.handlePerspectiveChange} | |||
onQueryChange={this.updateLocationQuery} | |||
onSortChange={this.handleSortChange} | |||
organization={this.props.organization} | |||
projects={this.state.projects} | |||
@@ -298,6 +300,7 @@ export default class AllProjects extends React.PureComponent<Props, State> { | |||
cardType={this.getView()} | |||
isFavorite={this.props.isFavorite} | |||
isFiltered={this.isFiltered()} | |||
onSonarCloud={this.props.onSonarCloud} | |||
organization={this.props.organization} | |||
projects={this.state.projects} | |||
query={this.state.query} | |||
@@ -319,7 +322,7 @@ export default class AllProjects extends React.PureComponent<Props, State> { | |||
{this.renderSide()} | |||
<div className="layout-page-main projects-page-content"> | |||
<div className="layout-page-main"> | |||
{this.renderHeader()} | |||
{this.renderMain()} | |||
</div> |
@@ -25,6 +25,7 @@ import { | |||
areThereCustomOrganizations, | |||
getGlobalSettingValue | |||
} from '../../../store/rootReducer'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface StateProps { | |||
currentUser: CurrentUser; | |||
@@ -32,6 +33,12 @@ interface StateProps { | |||
organizationsEnabled: boolean; | |||
} | |||
interface OwnProps { | |||
isFavorite: boolean; | |||
location: { pathname: string; query: RawQuery }; | |||
organization?: { key: string }; | |||
} | |||
const stateToProps = (state: any) => { | |||
const onSonarCloudSetting = getGlobalSettingValue(state, 'sonar.sonarcloud.enabled'); | |||
return { | |||
@@ -41,4 +48,6 @@ const stateToProps = (state: any) => { | |||
}; | |||
}; | |||
export default connect<StateProps, any, any>(stateToProps)(lazyLoad(() => import('./AllProjects'))); | |||
export default connect<StateProps, {}, OwnProps>(stateToProps)( | |||
lazyLoad(() => import('./AllProjects')) | |||
); |
@@ -0,0 +1,43 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 { translate } from '../../../helpers/l10n'; | |||
interface Props { | |||
onClearAll: () => void; | |||
} | |||
export default class ClearAll extends React.PureComponent<Props> { | |||
handleClick = (event: React.SyntheticEvent<HTMLButtonElement>) => { | |||
event.preventDefault(); | |||
event.currentTarget.blur(); | |||
this.props.onClearAll(); | |||
}; | |||
render() { | |||
return ( | |||
<div className="projects-facets-reset"> | |||
<button className="button-red" onClick={this.handleClick}> | |||
{translate('clear_all_filters')} | |||
</button> | |||
</div> | |||
); | |||
} | |||
} |
@@ -46,6 +46,10 @@ export default class DefaultPageSelector extends React.PureComponent<Props, Stat | |||
} | |||
componentDidMount() { | |||
if (this.props.onSonarCloud && !isLoggedIn(this.props.currentUser)) { | |||
this.context.router.replace('/explore/projects'); | |||
} | |||
if (!this.props.onSonarCloud) { | |||
this.defineIfShouldBeRedirected(); | |||
} | |||
@@ -98,15 +102,20 @@ export default class DefaultPageSelector extends React.PureComponent<Props, Stat | |||
} | |||
render() { | |||
if (this.props.onSonarCloud) { | |||
if (this.props.onSonarCloud && isLoggedIn(this.props.currentUser)) { | |||
return <AllProjectsContainer isFavorite={true} location={this.props.location} />; | |||
} | |||
const { shouldBeRedirected, shouldForceSorting } = this.state; | |||
if (shouldBeRedirected == null || shouldBeRedirected === true || shouldForceSorting != null) { | |||
return null; | |||
} else { | |||
if ( | |||
shouldBeRedirected !== undefined && | |||
shouldBeRedirected !== true && | |||
shouldForceSorting === undefined | |||
) { | |||
return <AllProjectsContainer isFavorite={false} location={this.props.location} />; | |||
} | |||
return null; | |||
} | |||
} |
@@ -21,13 +21,17 @@ import * as React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
export default function NoFavoriteProjects() { | |||
interface Props { | |||
onSonarCloud: boolean; | |||
} | |||
export default function NoFavoriteProjects({ onSonarCloud }: Props) { | |||
return ( | |||
<div className="projects-empty-list"> | |||
<h3>{translate('projects.no_favorite_projects')}</h3> | |||
<p className="big-spacer-top">{translate('projects.no_favorite_projects.engagement')}</p> | |||
<p className="big-spacer-top"> | |||
<Link to="/projects/all" className="button"> | |||
<Link to={onSonarCloud ? '/explore/projects' : '/projects/all'} className="button"> | |||
{translate('projects.explore_projects')} | |||
</Link> | |||
</p> |
@@ -30,9 +30,9 @@ import { Project } from '../types'; | |||
interface Props { | |||
currentUser: CurrentUser; | |||
isFavorite?: boolean; | |||
loading: boolean; | |||
onPerspectiveChange: (x: { view: string; visualization?: string }) => void; | |||
onQueryChange: (change: RawQuery) => void; | |||
onSortChange: (sort: string, desc: boolean) => void; | |||
organization?: { key: string }; | |||
projects?: Project[]; | |||
@@ -80,7 +80,7 @@ export default function PageHeader(props: Props) { | |||
)} | |||
<SearchFilterContainer | |||
isFavorite={props.isFavorite} | |||
onQueryChange={props.onQueryChange} | |||
organization={props.organization} | |||
query={props.query} | |||
/> |
@@ -18,9 +18,9 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { flatMap } from 'lodash'; | |||
import FavoriteFilterContainer from './FavoriteFilterContainer'; | |||
import ClearAll from './ClearAll'; | |||
import LanguagesFilterContainer from '../filters/LanguagesFilterContainer'; | |||
import CoverageFilter from '../filters/CoverageFilter'; | |||
import DuplicationsFilter from '../filters/DuplicationsFilter'; | |||
@@ -42,7 +42,8 @@ import { Facets } from '../types'; | |||
interface Props { | |||
facets?: Facets; | |||
isFavorite: boolean; | |||
onClearAll: () => void; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: RawQuery; | |||
showFavoriteFilter: boolean; | |||
@@ -51,15 +52,13 @@ interface Props { | |||
} | |||
export default function PageSidebar(props: Props) { | |||
const { facets, query, isFavorite, organization, view, visualization } = props; | |||
const { facets, onQueryChange, query, organization, view, visualization } = props; | |||
const isFiltered = Object.keys(query) | |||
.filter(key => !['view', 'visualization', 'sort'].includes(key)) | |||
.some(key => query[key] != null); | |||
const isLeakView = view === 'leak'; | |||
const basePathName = organization ? `/organizations/${organization.key}/projects` : '/projects'; | |||
const pathname = basePathName + (isFavorite ? '/favorite' : ''); | |||
const maxFacetValue = getMaxFacetValue(facets); | |||
const facetProps = { isFavorite, maxFacetValue, organization, query }; | |||
const facetProps = { onQueryChange, maxFacetValue, organization, query }; | |||
let linkQuery: RawQuery | undefined = undefined; | |||
if (view !== 'overall') { | |||
@@ -77,13 +76,7 @@ export default function PageSidebar(props: Props) { | |||
)} | |||
<div className="projects-facets-header clearfix"> | |||
{isFiltered && ( | |||
<div className="projects-facets-reset"> | |||
<Link to={{ pathname, query: linkQuery }} className="button button-red"> | |||
{translate('clear_all_filters')} | |||
</Link> | |||
</div> | |||
)} | |||
{isFiltered && <ClearAll onClearAll={props.onClearAll} />} | |||
<h3>{translate('filters')}</h3> | |||
</div> |
@@ -30,6 +30,7 @@ interface Props { | |||
cardType?: string; | |||
isFavorite: boolean; | |||
isFiltered: boolean; | |||
onSonarCloud: boolean; | |||
organization?: { key: string }; | |||
projects: Project[]; | |||
query: Query; | |||
@@ -41,7 +42,11 @@ export default class ProjectsList extends React.PureComponent<Props> { | |||
if (isFiltered) { | |||
return isFavorite ? <EmptyFavoriteSearch query={query} /> : <EmptySearch />; | |||
} | |||
return isFavorite ? <NoFavoriteProjects /> : <EmptyInstance />; | |||
return isFavorite ? ( | |||
<NoFavoriteProjects onSonarCloud={this.props.onSonarCloud} /> | |||
) : ( | |||
<EmptyInstance /> | |||
); | |||
} | |||
render() { |
@@ -0,0 +1,34 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* 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 { shallow } from 'enzyme'; | |||
import ClearAll from '../ClearAll'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
it('renders', () => { | |||
expect(shallow(<ClearAll onClearAll={jest.fn()} />)).toMatchSnapshot(); | |||
}); | |||
it('clears all', () => { | |||
const onClearAll = jest.fn(); | |||
const wrapper = shallow(<ClearAll onClearAll={onClearAll} />); | |||
click(wrapper.find('button')); | |||
expect(onClearAll).toBeCalled(); | |||
}); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import NoFavoriteProjects from '../NoFavoriteProjects'; | |||
it('renders', () => { | |||
expect(shallow(<NoFavoriteProjects />)).toMatchSnapshot(); | |||
expect(shallow(<NoFavoriteProjects onSonarCloud={false} />)).toMatchSnapshot(); | |||
}); |
@@ -73,6 +73,7 @@ function shallowRender(props?: {}) { | |||
currentUser={{ isLoggedIn: false }} | |||
loading={false} | |||
onPerspectiveChange={jest.fn()} | |||
onQueryChange={jest.fn()} | |||
onSortChange={jest.fn()} | |||
projects={[]} | |||
query={{ search: 'test' }} |
@@ -24,7 +24,8 @@ import PageSidebar from '../PageSidebar'; | |||
it('should render correctly', () => { | |||
const sidebar = shallow( | |||
<PageSidebar | |||
isFavorite={true} | |||
onClearAll={jest.fn()} | |||
onQueryChange={jest.fn()} | |||
query={{ size: '3' }} | |||
showFavoriteFilter={true} | |||
view="overall" | |||
@@ -37,7 +38,8 @@ it('should render correctly', () => { | |||
it('should render `leak` view correctly', () => { | |||
const sidebar = shallow( | |||
<PageSidebar | |||
isFavorite={false} | |||
onClearAll={jest.fn()} | |||
onQueryChange={jest.fn()} | |||
query={{ view: 'leak' }} | |||
showFavoriteFilter={true} | |||
view="leak" | |||
@@ -50,14 +52,15 @@ it('should render `leak` view correctly', () => { | |||
it('reset function should work correctly with view and visualizations', () => { | |||
const sidebar = shallow( | |||
<PageSidebar | |||
isFavorite={false} | |||
onClearAll={jest.fn()} | |||
onQueryChange={jest.fn()} | |||
query={{ view: 'visualizations', visualization: 'bugs' }} | |||
showFavoriteFilter={true} | |||
view="visualizations" | |||
visualization="bugs" | |||
/> | |||
); | |||
expect(sidebar.find('.projects-facets-reset').exists()).toBeFalsy(); | |||
expect(sidebar.find('ClearAll').exists()).toBeFalsy(); | |||
sidebar.setProps({ query: { size: '3' } }); | |||
expect(sidebar.find('.projects-facets-reset')).toMatchSnapshot(); | |||
expect(sidebar.find('ClearAll').exists()).toBeTruthy(); | |||
}); |
@@ -10,58 +10,11 @@ exports[`renders 1`] = ` | |||
encodeSpecialCharacters={true} | |||
title="projects.page" | |||
/> | |||
<div | |||
<ScreenPositionHelper | |||
className="layout-page-side-outer" | |||
> | |||
<div | |||
className="layout-page-side projects-page-side" | |||
style={ | |||
Object { | |||
"top": 30, | |||
} | |||
} | |||
> | |||
<div | |||
className="layout-page-side-inner" | |||
> | |||
<div | |||
className="layout-page-filters" | |||
> | |||
<PageSidebar | |||
isFavorite={false} | |||
query={ | |||
Object { | |||
"coverage": undefined, | |||
"duplications": undefined, | |||
"gate": undefined, | |||
"languages": undefined, | |||
"maintainability": undefined, | |||
"new_coverage": undefined, | |||
"new_duplications": undefined, | |||
"new_lines": undefined, | |||
"new_maintainability": undefined, | |||
"new_reliability": undefined, | |||
"new_security": undefined, | |||
"reliability": undefined, | |||
"search": undefined, | |||
"security": undefined, | |||
"size": undefined, | |||
"sort": undefined, | |||
"tags": undefined, | |||
"view": undefined, | |||
"visualization": undefined, | |||
} | |||
} | |||
showFavoriteFilter={true} | |||
view="overall" | |||
visualization="risk" | |||
/> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
/> | |||
<div | |||
className="layout-page-main projects-page-content" | |||
className="layout-page-main" | |||
> | |||
<div | |||
className="layout-page-header-panel layout-page-main-header" | |||
@@ -78,9 +31,9 @@ exports[`renders 1`] = ` | |||
"isLoggedIn": true, | |||
} | |||
} | |||
isFavorite={false} | |||
loading={false} | |||
onPerspectiveChange={[Function]} | |||
onQueryChange={[Function]} | |||
onSortChange={[Function]} | |||
projects={ | |||
Array [ | |||
@@ -129,6 +82,7 @@ exports[`renders 1`] = ` | |||
cardType="overall" | |||
isFavorite={false} | |||
isFiltered={false} | |||
onSonarCloud={false} | |||
projects={ | |||
Array [ | |||
Object { | |||
@@ -183,40 +137,11 @@ exports[`renders 2`] = ` | |||
encodeSpecialCharacters={true} | |||
title="projects.page" | |||
/> | |||
<div | |||
<ScreenPositionHelper | |||
className="layout-page-side-outer" | |||
> | |||
<div | |||
className="layout-page-side projects-page-side" | |||
style={ | |||
Object { | |||
"top": 30, | |||
} | |||
} | |||
> | |||
<div | |||
className="layout-page-side-inner" | |||
> | |||
<div | |||
className="layout-page-filters" | |||
> | |||
<PageSidebar | |||
isFavorite={false} | |||
query={ | |||
Object { | |||
"view": "visualizations", | |||
} | |||
} | |||
showFavoriteFilter={true} | |||
view="visualizations" | |||
visualization="risk" | |||
/> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
/> | |||
<div | |||
className="layout-page-main projects-page-content" | |||
className="layout-page-main" | |||
> | |||
<div | |||
className="layout-page-header-panel layout-page-main-header" | |||
@@ -233,9 +158,9 @@ exports[`renders 2`] = ` | |||
"isLoggedIn": true, | |||
} | |||
} | |||
isFavorite={false} | |||
loading={false} | |||
onPerspectiveChange={[Function]} | |||
onQueryChange={[Function]} | |||
onSortChange={[Function]} | |||
projects={ | |||
Array [ |
@@ -0,0 +1,14 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders 1`] = ` | |||
<div | |||
className="projects-facets-reset" | |||
> | |||
<button | |||
className="button-red" | |||
onClick={[Function]} | |||
> | |||
clear_all_filters | |||
</button> | |||
</div> | |||
`; |
@@ -17,6 +17,7 @@ exports[`should render correctly 1`] = ` | |||
view="overall" | |||
/> | |||
<SearchFilterContainer | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"search": "test", | |||
@@ -56,6 +57,7 @@ exports[`should render correctly while loading 1`] = ` | |||
view="overall" | |||
/> | |||
<SearchFilterContainer | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"search": "test", | |||
@@ -108,6 +110,7 @@ exports[`should render disabled sorting options for visualizations 1`] = ` | |||
</div> | |||
</Tooltip> | |||
<SearchFilterContainer | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"search": "test", |
@@ -1,28 +1,5 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`reset function should work correctly with view and visualizations 1`] = ` | |||
<div | |||
className="projects-facets-reset" | |||
> | |||
<Link | |||
className="button button-red" | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"view": "visualizations", | |||
"visualization": "bugs", | |||
}, | |||
} | |||
} | |||
> | |||
clear_all_filters | |||
</Link> | |||
</div> | |||
`; | |||
exports[`should render \`leak\` view correctly 1`] = ` | |||
<div> | |||
<Connect(FavoriteFilter) | |||
@@ -40,7 +17,7 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
</h3> | |||
</div> | |||
<QualityGateFilter | |||
isFavorite={false} | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -48,8 +25,8 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<NewReliabilityFilter | |||
isFavorite={false} | |||
key="new_reliability" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -57,8 +34,8 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<NewSecurityFilter | |||
isFavorite={false} | |||
key="new_security" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -66,8 +43,8 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<NewMaintainabilityFilter | |||
isFavorite={false} | |||
key="new_maintainability" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -75,8 +52,8 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<NewCoverageFilter | |||
isFavorite={false} | |||
key="new_coverage" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -84,8 +61,8 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<NewDuplicationsFilter | |||
isFavorite={false} | |||
key="new_duplications" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -93,8 +70,8 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<NewLinesFilter | |||
isFavorite={false} | |||
key="new_lines" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -102,7 +79,7 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<Connect(LanguagesFilter) | |||
isFavorite={false} | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -110,7 +87,7 @@ exports[`should render \`leak\` view correctly 1`] = ` | |||
} | |||
/> | |||
<TagsFilter | |||
isFavorite={false} | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"view": "leak", | |||
@@ -126,29 +103,15 @@ exports[`should render correctly 1`] = ` | |||
<div | |||
className="projects-facets-header clearfix" | |||
> | |||
<div | |||
className="projects-facets-reset" | |||
> | |||
<Link | |||
className="button button-red" | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": undefined, | |||
} | |||
} | |||
> | |||
clear_all_filters | |||
</Link> | |||
</div> | |||
<ClearAll | |||
onClearAll={[Function]} | |||
/> | |||
<h3> | |||
filters | |||
</h3> | |||
</div> | |||
<QualityGateFilter | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -156,8 +119,8 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<ReliabilityFilter | |||
isFavorite={true} | |||
key="reliability" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -165,8 +128,8 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<SecurityFilter | |||
isFavorite={true} | |||
key="security" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -174,8 +137,8 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<MaintainabilityFilter | |||
isFavorite={true} | |||
key="maintainability" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -183,8 +146,8 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<CoverageFilter | |||
isFavorite={true} | |||
key="coverage" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -192,8 +155,8 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<DuplicationsFilter | |||
isFavorite={true} | |||
key="duplications" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -201,8 +164,8 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<SizeFilter | |||
isFavorite={true} | |||
key="size" | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -211,7 +174,7 @@ exports[`should render correctly 1`] = ` | |||
value="3" | |||
/> | |||
<Connect(LanguagesFilter) | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", | |||
@@ -219,7 +182,7 @@ exports[`should render correctly 1`] = ` | |||
} | |||
/> | |||
<TagsFilter | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
query={ | |||
Object { | |||
"size": "3", |
@@ -24,12 +24,13 @@ import CoverageRating from '../../../components/ui/CoverageRating'; | |||
import { getCoverageRatingLabel, getCoverageRatingAverageValue } from '../../../helpers/ratings'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
export interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property?: string; | |||
query: { [x: string]: any }; | |||
@@ -43,13 +44,13 @@ export default function CoverageFilter(props: Props) { | |||
<Filter | |||
facet={props.facet} | |||
maxFacetValue={props.maxFacetValue} | |||
onQueryChange={props.onQueryChange} | |||
value={props.value} | |||
property={property} | |||
className={props.className} | |||
options={[1, 2, 3, 4, 5, 6]} | |||
query={props.query} | |||
renderOption={renderOption} | |||
isFavorite={props.isFavorite} | |||
organization={props.organization} | |||
getFacetValueForOption={getFacetValueForOption} | |||
highlightUnder={1} |
@@ -27,12 +27,13 @@ import { | |||
} from '../../../helpers/ratings'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
export interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property?: string; | |||
query: { [x: string]: any }; | |||
@@ -45,13 +46,13 @@ export default function DuplicationsFilter(props: Props) { | |||
<Filter | |||
facet={props.facet} | |||
maxFacetValue={props.maxFacetValue} | |||
onQueryChange={props.onQueryChange} | |||
value={props.value} | |||
property={property} | |||
className={props.className} | |||
options={[1, 2, 3, 4, 5, 6]} | |||
query={props.query} | |||
renderOption={renderOption} | |||
isFavorite={props.isFavorite} | |||
organization={props.organization} | |||
getFacetValueForOption={getFacetValueForOption} | |||
highlightUnder={1} |
@@ -19,17 +19,17 @@ | |||
*/ | |||
import * as React from 'react'; | |||
import * as classNames from 'classnames'; | |||
import { Link } from 'react-router'; | |||
import { getFilterUrl } from './utils'; | |||
import { formatMeasure } from '../../../helpers/measures'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
export type Option = string | number; | |||
interface Props { | |||
property: string; | |||
className?: string; | |||
onQueryChange: (change: RawQuery) => void; | |||
options: Option[]; | |||
query: { [x: string]: any }; | |||
renderOption: (option: Option, isSelected: boolean) => React.ReactNode; | |||
@@ -38,7 +38,6 @@ interface Props { | |||
facet?: Facet; | |||
maxFacetValue?: number; | |||
optionClassName?: string; | |||
isFavorite?: boolean; | |||
organization?: { key: string }; | |||
getFacetValueForOption?: (facet: Facet, option: Option) => void; | |||
@@ -54,7 +53,7 @@ interface Props { | |||
export default class Filter extends React.PureComponent<Props> { | |||
isSelected(option: Option): boolean { | |||
const { value } = this.props; | |||
return Array.isArray(value) ? value.includes(option) : option === value; | |||
return Array.isArray(value) ? value.includes(option) : String(option) === String(value); | |||
} | |||
highlightUnder(option?: Option): boolean { | |||
@@ -66,23 +65,28 @@ export default class Filter extends React.PureComponent<Props> { | |||
); | |||
} | |||
blurOnClick = (event: React.SyntheticEvent<HTMLElement>) => event.currentTarget.blur(); | |||
handleClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => { | |||
event.preventDefault(); | |||
event.currentTarget.blur(); | |||
getPath(option: Option) { | |||
const { property, value } = this.props; | |||
const { key: option } = event.currentTarget.dataset; | |||
let urlOption; | |||
if (Array.isArray(value)) { | |||
if (this.isSelected(option)) { | |||
urlOption = value.length > 1 ? value.filter(val => val !== option).join(',') : null; | |||
if (option) { | |||
if (Array.isArray(value)) { | |||
if (this.isSelected(option)) { | |||
urlOption = value.length > 1 ? value.filter(val => val !== option).join(',') : null; | |||
} else { | |||
urlOption = value.concat(option).join(','); | |||
} | |||
} else { | |||
urlOption = value.concat(option).join(','); | |||
urlOption = this.isSelected(option) ? null : option; | |||
} | |||
} else { | |||
urlOption = this.isSelected(option) ? null : option; | |||
this.props.onQueryChange({ [property]: urlOption }); | |||
} | |||
return getFilterUrl(this.props, { [property]: urlOption }); | |||
} | |||
}; | |||
renderOptionBar(facetValue: number | undefined) { | |||
if (facetValue === undefined || !this.props.maxFacetValue) { | |||
@@ -111,7 +115,6 @@ export default class Filter extends React.PureComponent<Props> { | |||
this.props.optionClassName | |||
); | |||
const path = this.getPath(option); | |||
const facetValue = | |||
facet && getFacetValueForOption ? getFacetValueForOption(facet, option) : undefined; | |||
@@ -122,12 +125,7 @@ export default class Filter extends React.PureComponent<Props> { | |||
option > value; | |||
return ( | |||
<Link | |||
key={option} | |||
className={className} | |||
to={path} | |||
data-key={option} | |||
onClick={this.blurOnClick}> | |||
<a className={className} data-key={option} href="#" key={option} onClick={this.handleClick}> | |||
<span className="facet-name"> | |||
{this.props.renderOption(option, this.isSelected(option) || isUnderSelectedOption)} | |||
</span> | |||
@@ -137,7 +135,7 @@ export default class Filter extends React.PureComponent<Props> { | |||
{this.renderOptionBar(facetValue)} | |||
</span> | |||
)} | |||
</Link> | |||
</a> | |||
); | |||
} | |||
@@ -23,14 +23,15 @@ import FilterHeader from './FilterHeader'; | |||
import Rating from '../../../components/ui/Rating'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
headerDetail?: React.ReactNode; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
name: string; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property: string; | |||
query: { [x: string]: any }; | |||
@@ -42,13 +43,13 @@ export default function IssuesFilter(props: Props) { | |||
<Filter | |||
facet={props.facet} | |||
maxFacetValue={props.maxFacetValue} | |||
onQueryChange={props.onQueryChange} | |||
value={props.value} | |||
property={props.property} | |||
className={props.className} | |||
options={[1, 2, 3, 4, 5]} | |||
query={props.query} | |||
renderOption={renderOption} | |||
isFavorite={props.isFavorite} | |||
organization={props.organization} | |||
getFacetValueForOption={getFacetValueForOption} | |||
highlightUnder={1} |
@@ -26,12 +26,13 @@ import SearchableFilterOption from './SearchableFilterOption'; | |||
import { getLanguageByKey, Languages } from '../../../store/languages/reducer'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
languages: Languages; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property?: string; | |||
query: { [x: string]: any }; | |||
@@ -68,6 +69,7 @@ export default class LanguagesFilter extends React.Component<Props> { | |||
return ( | |||
<Filter | |||
onQueryChange={this.props.onQueryChange} | |||
property={property} | |||
options={this.getSortedOptions(this.props.facet)} | |||
query={this.props.query} | |||
@@ -75,13 +77,12 @@ export default class LanguagesFilter extends React.Component<Props> { | |||
value={this.props.value} | |||
facet={this.props.facet} | |||
maxFacetValue={this.props.maxFacetValue} | |||
isFavorite={this.props.isFavorite} | |||
organization={this.props.organization} | |||
getFacetValueForOption={this.getFacetValueForOption} | |||
header={<FilterHeader name={translate('projects.facets.languages')} />} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={this.props.isFavorite} | |||
onQueryChange={this.props.onQueryChange} | |||
organization={this.props.organization} | |||
options={this.getSearchOptions()} | |||
property={property} |
@@ -22,13 +22,14 @@ import IssuesFilter from './IssuesFilter'; | |||
import { Facet } from '../types'; | |||
import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
headerDetail?: React.ReactNode; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; |
@@ -23,12 +23,13 @@ import FilterHeader from './FilterHeader'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getSizeRatingLabel } from '../../../helpers/ratings'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
export interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property?: string; | |||
query: { [x: string]: any }; | |||
@@ -42,13 +43,13 @@ export default function NewLinesFilter(props: Props) { | |||
<Filter | |||
facet={props.facet} | |||
maxFacetValue={props.maxFacetValue} | |||
onQueryChange={props.onQueryChange} | |||
value={props.value} | |||
property={property} | |||
className="leak-facet-box" | |||
options={[1, 2, 3, 4, 5]} | |||
query={props.query} | |||
renderOption={renderOption} | |||
isFavorite={props.isFavorite} | |||
organization={props.organization} | |||
getFacetValueForOption={getFacetValueForOption} | |||
highlightUnder={1} |
@@ -22,12 +22,13 @@ import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; | |||
import IssuesFilter from './IssuesFilter'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; |
@@ -22,12 +22,13 @@ import BugIcon from '../../../components/icons-components/BugIcon'; | |||
import IssuesFilter from './IssuesFilter'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; |
@@ -22,12 +22,13 @@ import VulnerabilityIcon from '../../../components/icons-components/Vulnerabilit | |||
import IssuesFilter from './IssuesFilter'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; |
@@ -20,15 +20,16 @@ | |||
import * as React from 'react'; | |||
import Filter from './Filter'; | |||
import FilterHeader from './FilterHeader'; | |||
import { Facet } from '../types'; | |||
import Level from '../../../components/ui/Level'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
export interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; | |||
@@ -39,12 +40,12 @@ export default function QualityGateFilter(props: Props) { | |||
<Filter | |||
facet={props.facet} | |||
maxFacetValue={props.maxFacetValue} | |||
onQueryChange={props.onQueryChange} | |||
value={props.value} | |||
property="gate" | |||
options={['OK', 'WARN', 'ERROR']} | |||
query={props.query} | |||
renderOption={renderOption} | |||
isFavorite={props.isFavorite} | |||
organization={props.organization} | |||
getFacetValueForOption={getFacetValueForOption} | |||
header={<FilterHeader name={translate('projects.facets.quality_gate')} />} |
@@ -22,13 +22,14 @@ import IssuesFilter from './IssuesFilter'; | |||
import { Facet } from '../types'; | |||
import BugIcon from '../../../components/icons-components/BugIcon'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
headerDetail?: React.ReactNode; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; |
@@ -18,26 +18,20 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import * as PropTypes from 'prop-types'; | |||
import { getFilterUrl } from './utils'; | |||
import SearchBox from '../../../components/controls/SearchBox'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
query: { search?: string }; | |||
isFavorite?: boolean; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
} | |||
export default class SearchFilterContainer extends React.PureComponent<Props> { | |||
static contextTypes = { | |||
router: PropTypes.object.isRequired | |||
}; | |||
handleSearch = (userQuery?: string) => { | |||
const path = getFilterUrl(this.props, { search: userQuery }); | |||
this.context.router.push(path); | |||
this.props.onQueryChange({ search: userQuery }); | |||
}; | |||
render() { |
@@ -18,12 +18,12 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import * as PropTypes from 'prop-types'; | |||
import { getFilterUrl } from './utils'; | |||
import Select from '../../../components/controls/Select'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
onQueryChange: (change: RawQuery) => void; | |||
property: string; | |||
query: { [x: string]: any }; | |||
options: Array<{ label: string; value: string }>; | |||
@@ -35,14 +35,9 @@ interface Props { | |||
} | |||
export default class SearchableFilterFooter extends React.PureComponent<Props> { | |||
static contextTypes = { | |||
router: PropTypes.object.isRequired | |||
}; | |||
handleOptionChange = ({ value }: { value: string }) => { | |||
const urlOptions = (this.props.query[this.props.property] || []).concat(value).join(','); | |||
const path = getFilterUrl(this.props, { [this.props.property]: urlOptions }); | |||
this.context.router.push(path); | |||
this.props.onQueryChange({ [this.props.property]: urlOptions }); | |||
}; | |||
render() { |
@@ -22,13 +22,14 @@ import IssuesFilter from './IssuesFilter'; | |||
import { Facet } from '../types'; | |||
import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
headerDetail?: React.ReactNode; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
query: { [x: string]: any }; | |||
value?: any; |
@@ -24,12 +24,13 @@ import SizeRating from '../../../components/ui/SizeRating'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getSizeRatingLabel, getSizeRatingAverageValue } from '../../../helpers/ratings'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
export interface Props { | |||
className?: string; | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property?: string; | |||
query: { [x: string]: any }; | |||
@@ -43,13 +44,13 @@ export default function SizeFilter(props: Props) { | |||
<Filter | |||
facet={props.facet} | |||
maxFacetValue={props.maxFacetValue} | |||
onQueryChange={props.onQueryChange} | |||
value={props.value} | |||
property={property} | |||
className={props.className} | |||
options={[1, 2, 3, 4, 5]} | |||
query={props.query} | |||
renderOption={renderOption} | |||
isFavorite={props.isFavorite} | |||
organization={props.organization} | |||
getFacetValueForOption={getFacetValueForOption} | |||
highlightUnder={1} |
@@ -26,11 +26,12 @@ import SearchableFilterOption from './SearchableFilterOption'; | |||
import { searchProjectTags } from '../../../api/components'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Facet } from '../types'; | |||
import { RawQuery } from '../../../helpers/query'; | |||
interface Props { | |||
facet?: Facet; | |||
isFavorite?: boolean; | |||
maxFacetValue?: number; | |||
onQueryChange: (change: RawQuery) => void; | |||
organization?: { key: string }; | |||
property?: string; | |||
query: { [x: string]: any }; | |||
@@ -101,6 +102,7 @@ export default class TagsFilter extends React.PureComponent<Props, State> { | |||
return ( | |||
<Filter | |||
onQueryChange={this.props.onQueryChange} | |||
property={property} | |||
options={this.getSortedOptions(this.props.facet)} | |||
query={this.props.query} | |||
@@ -108,13 +110,12 @@ export default class TagsFilter extends React.PureComponent<Props, State> { | |||
value={this.props.value} | |||
facet={this.props.facet} | |||
maxFacetValue={this.props.maxFacetValue} | |||
isFavorite={this.props.isFavorite} | |||
organization={this.props.organization} | |||
getFacetValueForOption={this.getFacetValueForOption} | |||
header={<FilterHeader name={translate('projects.facets.tags')} />} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={this.props.isFavorite} | |||
onQueryChange={this.props.onQueryChange} | |||
isLoading={this.state.isLoading} | |||
onInputChange={this.handleSearch} | |||
onOpen={this.handleSearch} |
@@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; | |||
import CoverageFilter from '../CoverageFilter'; | |||
it('renders', () => { | |||
const wrapper = shallow(<CoverageFilter query={{}} />); | |||
const wrapper = shallow(<CoverageFilter onQueryChange={jest.fn()} query={{}} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
const renderOption = wrapper.prop('renderOption'); |
@@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; | |||
import DuplicationsFilter from '../DuplicationsFilter'; | |||
it('renders', () => { | |||
const wrapper = shallow(<DuplicationsFilter query={{}} />); | |||
const wrapper = shallow(<DuplicationsFilter onQueryChange={jest.fn()} query={{}} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
const renderOption = wrapper.prop('renderOption'); |
@@ -63,6 +63,7 @@ it('renders facet bar chart', () => { | |||
function shallowRender(props?: any) { | |||
return shallow( | |||
<Filter | |||
onQueryChange={jest.fn()} | |||
options={[1, 2, 3]} | |||
property="foo" | |||
query={{}} |
@@ -22,7 +22,9 @@ import { shallow } from 'enzyme'; | |||
import IssuesFilter from '../IssuesFilter'; | |||
it('renders', () => { | |||
const wrapper = shallow(<IssuesFilter name="bugs" property="bugs" query={{}} />); | |||
const wrapper = shallow( | |||
<IssuesFilter name="bugs" onQueryChange={jest.fn()} property="bugs" query={{}} /> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
const renderOption = wrapper.prop('renderOption'); |
@@ -34,7 +34,12 @@ const languagesFacet = { java: 39, cs: 4, js: 1 }; | |||
it('should render the languages without the ones in the facet', () => { | |||
const wrapper = shallow( | |||
<LanguagesFilter facet={languagesFacet} languages={languages} query={{ languages: null }} /> | |||
<LanguagesFilter | |||
facet={languagesFacet} | |||
languages={languages} | |||
onQueryChange={jest.fn()} | |||
query={{ languages: null }} | |||
/> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
@@ -43,8 +48,8 @@ it('should render the languages facet with the selected languages', () => { | |||
const wrapper = shallow( | |||
<LanguagesFilter | |||
facet={languagesFacet} | |||
isFavorite={true} | |||
languages={languages} | |||
onQueryChange={jest.fn()} | |||
query={{ languages: ['java', 'cs'] }} | |||
value={['java', 'cs']} | |||
/> | |||
@@ -69,8 +74,8 @@ it('should render maximum 10 languages in the searchbox results', () => { | |||
const wrapper = shallow( | |||
<LanguagesFilter | |||
facet={{ ...languagesFacet, g: 1 }} | |||
isFavorite={true} | |||
languages={manyLanguages} | |||
onQueryChange={jest.fn()} | |||
query={{ languages: ['java', 'g'] }} | |||
value={['java', 'g']} | |||
/> |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import MaintainabilityFilter from '../MaintainabilityFilter'; | |||
it('renders', () => { | |||
expect(shallow(<MaintainabilityFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<MaintainabilityFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import NewCoverageFilter from '../NewCoverageFilter'; | |||
it('renders', () => { | |||
expect(shallow(<NewCoverageFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<NewCoverageFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import NewDuplicationsFilter from '../NewDuplicationsFilter'; | |||
it('renders', () => { | |||
expect(shallow(<NewDuplicationsFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<NewDuplicationsFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; | |||
import NewLinesFilter from '../NewLinesFilter'; | |||
it('renders', () => { | |||
const wrapper = shallow(<NewLinesFilter query={{}} />); | |||
const wrapper = shallow(<NewLinesFilter onQueryChange={jest.fn()} query={{}} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
const renderOption = wrapper.prop('renderOption'); |
@@ -22,5 +22,7 @@ import { shallow } from 'enzyme'; | |||
import NewMaintainabilityFilter from '../NewMaintainabilityFilter'; | |||
it('renders', () => { | |||
expect(shallow(<NewMaintainabilityFilter query={{}} />)).toMatchSnapshot(); | |||
expect( | |||
shallow(<NewMaintainabilityFilter onQueryChange={jest.fn()} query={{}} />) | |||
).toMatchSnapshot(); | |||
}); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import NewReliabilityFilter from '../NewReliabilityFilter'; | |||
it('renders', () => { | |||
expect(shallow(<NewReliabilityFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<NewReliabilityFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import NewSecurityFilter from '../NewSecurityFilter'; | |||
it('renders', () => { | |||
expect(shallow(<NewSecurityFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<NewSecurityFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; | |||
import QualityGateFilter from '../QualityGateFilter'; | |||
it('renders', () => { | |||
const wrapper = shallow(<QualityGateFilter query={{}} />); | |||
const wrapper = shallow(<QualityGateFilter onQueryChange={jest.fn()} query={{}} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
const renderOption = wrapper.prop('renderOption'); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import ReliabilityFilter from '../ReliabilityFilter'; | |||
it('renders', () => { | |||
expect(shallow(<ReliabilityFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<ReliabilityFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,9 +22,11 @@ import { shallow } from 'enzyme'; | |||
import SearchFilterContainer from '../SearchFilterContainer'; | |||
it('searches', () => { | |||
const push = jest.fn(); | |||
const wrapper = shallow(<SearchFilterContainer query={{}} />, { context: { router: { push } } }); | |||
const onQueryChange = jest.fn(); | |||
const wrapper = shallow(<SearchFilterContainer onQueryChange={onQueryChange} query={{}} />, { | |||
context: { router: { push: jest.fn() } } | |||
}); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('SearchBox').prop<Function>('onChange')('foo'); | |||
expect(push).toBeCalledWith({ pathname: '/projects', query: { search: 'foo' } }); | |||
expect(onQueryChange).toBeCalledWith({ search: 'foo' }); | |||
}); |
@@ -30,6 +30,7 @@ const options = [ | |||
it('should render items without the ones in the facet', () => { | |||
const wrapper = shallow( | |||
<SearchableFilterFooter | |||
onQueryChange={jest.fn()} | |||
property="languages" | |||
query={{ languages: ['java'] }} | |||
options={options} | |||
@@ -40,18 +41,16 @@ it('should render items without the ones in the facet', () => { | |||
}); | |||
it('should render items without the ones in the facet', () => { | |||
const push = jest.fn(); | |||
const onQueryChange = jest.fn(); | |||
const wrapper = shallow( | |||
<SearchableFilterFooter | |||
onQueryChange={onQueryChange} | |||
property="languages" | |||
query={{ languages: ['java'] }} | |||
options={options} | |||
/>, | |||
{ context: { router: { push } } } | |||
{ context: { router: { push: jest.fn() } } } | |||
); | |||
(wrapper.find('Select').prop('onChange') as Function)({ value: 'js' }); | |||
expect(push).toBeCalledWith({ | |||
pathname: '/projects', | |||
query: { languages: 'java,js' } | |||
}); | |||
expect(onQueryChange).toBeCalledWith({ languages: 'java,js' }); | |||
}); |
@@ -22,5 +22,5 @@ import { shallow } from 'enzyme'; | |||
import SecurityFilter from '../SecurityFilter'; | |||
it('renders', () => { | |||
expect(shallow(<SecurityFilter query={{}} />)).toMatchSnapshot(); | |||
expect(shallow(<SecurityFilter onQueryChange={jest.fn()} query={{}} />)).toMatchSnapshot(); | |||
}); |
@@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; | |||
import SizeFilter from '../SizeFilter'; | |||
it('renders', () => { | |||
const wrapper = shallow(<SizeFilter query={{}} />); | |||
const wrapper = shallow(<SizeFilter onQueryChange={jest.fn()} query={{}} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
const renderOption = wrapper.prop('renderOption'); |
@@ -25,7 +25,9 @@ const tags = ['lang', 'sonar', 'csharp', 'dotnet', 'it', 'net']; | |||
const tagsFacet = { lang: 4, sonar: 3, csharp: 1 }; | |||
it('should render the tags without the ones in the facet', () => { | |||
const wrapper = shallow(<TagsFilter query={{ tags: null }} facet={tagsFacet} />); | |||
const wrapper = shallow( | |||
<TagsFilter onQueryChange={jest.fn()} query={{ tags: null }} facet={tagsFacet} /> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.setState({ tags }); | |||
expect(wrapper).toMatchSnapshot(); | |||
@@ -34,10 +36,10 @@ it('should render the tags without the ones in the facet', () => { | |||
it('should render the tags facet with the selected tags', () => { | |||
const wrapper = shallow( | |||
<TagsFilter | |||
onQueryChange={jest.fn()} | |||
query={{ tags: ['lang', 'sonar'] }} | |||
value={['lang', 'sonar']} | |||
facet={tagsFacet} | |||
isFavorite={true} | |||
/> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
@@ -47,10 +49,10 @@ it('should render the tags facet with the selected tags', () => { | |||
it('should render maximum 10 tags in the searchbox results', () => { | |||
const wrapper = shallow( | |||
<TagsFilter | |||
onQueryChange={jest.fn()} | |||
query={{ languages: ['java', 'ad'] }} | |||
value={['java', 'ad']} | |||
facet={{ ...tagsFacet, ad: 1 }} | |||
isFavorite={true} | |||
/> | |||
); | |||
wrapper.setState({ tags: [...tags, 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag', 'ah', 'ai'] }); |
@@ -10,6 +10,7 @@ exports[`renders 1`] = ` | |||
} | |||
highlightUnder={1} | |||
highlightUnderMax={5} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
1, |
@@ -10,6 +10,7 @@ exports[`renders 1`] = ` | |||
} | |||
highlightUnder={1} | |||
highlightUnderMax={5} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
1, |
@@ -8,75 +8,48 @@ exports[`highlights under 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={1} | |||
href="#" | |||
key="1" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 1, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
</a> | |||
<div | |||
className="search-navigator-facet-highlight-under-container" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={2} | |||
href="#" | |||
key="2" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 2, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
2 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={3} | |||
href="#" | |||
key="3" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 3, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -90,73 +63,48 @@ exports[`hightlights under selected 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={1} | |||
href="#" | |||
key="1" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 1, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
</a> | |||
<div | |||
className="search-navigator-facet-highlight-under-container" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key={2} | |||
href="#" | |||
key="2" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object {}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
2 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={3} | |||
href="#" | |||
key="3" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 3, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -170,72 +118,45 @@ exports[`renders 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={1} | |||
href="#" | |||
key="1" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 1, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={2} | |||
href="#" | |||
key="2" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 2, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
2 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={3} | |||
href="#" | |||
key="3" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 3, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
</div> | |||
`; | |||
@@ -248,21 +169,12 @@ exports[`renders facet bar chart 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key="a" | |||
href="#" | |||
key="a" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": "a", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -286,22 +198,13 @@ exports[`renders facet bar chart 1`] = ` | |||
/> | |||
</div> | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key="b" | |||
href="#" | |||
key="b" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": "b", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -325,22 +228,13 @@ exports[`renders facet bar chart 1`] = ` | |||
/> | |||
</div> | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key="c" | |||
href="#" | |||
key="c" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": "c", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -364,7 +258,7 @@ exports[`renders facet bar chart 1`] = ` | |||
/> | |||
</div> | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
</div> | |||
`; | |||
@@ -378,72 +272,45 @@ exports[`renders header and footer 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={1} | |||
href="#" | |||
key="1" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 1, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={2} | |||
href="#" | |||
key="2" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 2, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
2 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={3} | |||
href="#" | |||
key="3" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 3, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
<footer /> | |||
</div> | |||
@@ -457,72 +324,45 @@ exports[`renders multiple selected 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key={1} | |||
href="#" | |||
key="1" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": "2", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key={2} | |||
href="#" | |||
key="2" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": "1", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
2 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={3} | |||
href="#" | |||
key="3" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": "1,2,3", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
</div> | |||
`; | |||
@@ -548,70 +388,45 @@ exports[`renders selected 1`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={1} | |||
href="#" | |||
key="1" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 1, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key={2} | |||
href="#" | |||
key="2" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object {}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
2 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key={3} | |||
href="#" | |||
key="3" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects", | |||
"query": Object { | |||
"foo": 3, | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
</div> | |||
`; |
@@ -9,6 +9,7 @@ exports[`renders 1`] = ` | |||
/> | |||
} | |||
highlightUnder={1} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
1, |
@@ -12,7 +12,7 @@ exports[`should render maximum 10 languages in the searchbox results 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -75,7 +75,7 @@ exports[`should render maximum 10 languages in the searchbox results 1`] = ` | |||
name="projects.facets.languages" | |||
/> | |||
} | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"java", | |||
@@ -114,7 +114,7 @@ exports[`should render the languages facet with the selected languages 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -149,7 +149,7 @@ exports[`should render the languages facet with the selected languages 1`] = ` | |||
name="projects.facets.languages" | |||
/> | |||
} | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"java", | |||
@@ -187,21 +187,12 @@ exports[`should render the languages facet with the selected languages 2`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key="java" | |||
href="#" | |||
key="java" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": Object { | |||
"languages": "cs", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -221,22 +212,13 @@ exports[`should render the languages facet with the selected languages 2`] = ` | |||
> | |||
39 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key="cs" | |||
href="#" | |||
key="cs" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": Object { | |||
"languages": "java", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -256,22 +238,13 @@ exports[`should render the languages facet with the selected languages 2`] = ` | |||
> | |||
4 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key="js" | |||
href="#" | |||
key="js" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": Object { | |||
"languages": "java,cs,js", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -291,10 +264,10 @@ exports[`should render the languages facet with the selected languages 2`] = ` | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
<SearchableFilterFooter | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -335,7 +308,7 @@ exports[`should render the languages without the ones in the facet 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={undefined} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -367,6 +340,7 @@ exports[`should render the languages without the ones in the facet 1`] = ` | |||
name="projects.facets.languages" | |||
/> | |||
} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"java", |
@@ -15,6 +15,7 @@ exports[`renders 1`] = ` | |||
</span> | |||
} | |||
name="Maintainability" | |||
onQueryChange={[Function]} | |||
property="maintainability" | |||
query={Object {}} | |||
/> |
@@ -3,6 +3,7 @@ | |||
exports[`renders 1`] = ` | |||
<CoverageFilter | |||
className="leak-facet-box" | |||
onQueryChange={[Function]} | |||
property="new_coverage" | |||
query={Object {}} | |||
/> |
@@ -3,6 +3,7 @@ | |||
exports[`renders 1`] = ` | |||
<DuplicationsFilter | |||
className="leak-facet-box" | |||
onQueryChange={[Function]} | |||
property="new_duplications" | |||
query={Object {}} | |||
/> |
@@ -10,6 +10,7 @@ exports[`renders 1`] = ` | |||
/> | |||
} | |||
highlightUnder={1} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
1, |
@@ -16,6 +16,7 @@ exports[`renders 1`] = ` | |||
</span> | |||
} | |||
name="Maintainability" | |||
onQueryChange={[Function]} | |||
property="new_maintainability" | |||
query={Object {}} | |||
/> |
@@ -16,6 +16,7 @@ exports[`renders 1`] = ` | |||
</span> | |||
} | |||
name="Reliability" | |||
onQueryChange={[Function]} | |||
property="new_reliability" | |||
query={Object {}} | |||
/> |
@@ -16,6 +16,7 @@ exports[`renders 1`] = ` | |||
</span> | |||
} | |||
name="Security" | |||
onQueryChange={[Function]} | |||
property="new_security" | |||
query={Object {}} | |||
/> |
@@ -8,6 +8,7 @@ exports[`renders 1`] = ` | |||
name="projects.facets.quality_gate" | |||
/> | |||
} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"OK", |
@@ -15,6 +15,7 @@ exports[`renders 1`] = ` | |||
</span> | |||
} | |||
name="Reliability" | |||
onQueryChange={[Function]} | |||
property="reliability" | |||
query={Object {}} | |||
/> |
@@ -15,6 +15,7 @@ exports[`renders 1`] = ` | |||
</span> | |||
} | |||
name="Security" | |||
onQueryChange={[Function]} | |||
property="security" | |||
query={Object {}} | |||
/> |
@@ -9,6 +9,7 @@ exports[`renders 1`] = ` | |||
/> | |||
} | |||
highlightUnder={1} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
1, |
@@ -12,10 +12,10 @@ exports[`should render maximum 10 tags in the searchbox results 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={true} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -78,7 +78,7 @@ exports[`should render maximum 10 tags in the searchbox results 1`] = ` | |||
name="projects.facets.tags" | |||
/> | |||
} | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"lang", | |||
@@ -117,10 +117,10 @@ exports[`should render the tags facet with the selected tags 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={true} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
onQueryChange={[Function]} | |||
options={Array []} | |||
organization={undefined} | |||
property="tags" | |||
@@ -140,7 +140,7 @@ exports[`should render the tags facet with the selected tags 1`] = ` | |||
name="projects.facets.tags" | |||
/> | |||
} | |||
isFavorite={true} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"lang", | |||
@@ -178,21 +178,12 @@ exports[`should render the tags facet with the selected tags 2`] = ` | |||
<div | |||
className="search-navigator-facet-list projects-facet-list" | |||
> | |||
<Link | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key="lang" | |||
href="#" | |||
key="lang" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": Object { | |||
"tags": "sonar", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -206,22 +197,13 @@ exports[`should render the tags facet with the selected tags 2`] = ` | |||
> | |||
4 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet active" | |||
data-key="sonar" | |||
href="#" | |||
key="sonar" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": Object { | |||
"tags": "lang", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -235,22 +217,13 @@ exports[`should render the tags facet with the selected tags 2`] = ` | |||
> | |||
3 | |||
</span> | |||
</Link> | |||
<Link | |||
</a> | |||
<a | |||
className="facet search-navigator-facet projects-facet" | |||
data-key="csharp" | |||
href="#" | |||
key="csharp" | |||
onClick={[Function]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/projects/favorite", | |||
"query": Object { | |||
"tags": "lang,sonar,csharp", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="facet-name" | |||
@@ -264,13 +237,13 @@ exports[`should render the tags facet with the selected tags 2`] = ` | |||
> | |||
1 | |||
</span> | |||
</Link> | |||
</a> | |||
</div> | |||
<SearchableFilterFooter | |||
isFavorite={true} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
onQueryChange={[Function]} | |||
options={Array []} | |||
property="tags" | |||
query={ | |||
@@ -296,10 +269,10 @@ exports[`should render the tags without the ones in the facet 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={undefined} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
onQueryChange={[Function]} | |||
options={Array []} | |||
organization={undefined} | |||
property="tags" | |||
@@ -316,6 +289,7 @@ exports[`should render the tags without the ones in the facet 1`] = ` | |||
name="projects.facets.tags" | |||
/> | |||
} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"lang", | |||
@@ -344,10 +318,10 @@ exports[`should render the tags without the ones in the facet 2`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={undefined} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -379,6 +353,7 @@ exports[`should render the tags without the ones in the facet 2`] = ` | |||
name="projects.facets.tags" | |||
/> | |||
} | |||
onQueryChange={[Function]} | |||
options={ | |||
Array [ | |||
"lang", |
@@ -1,11 +1,3 @@ | |||
.projects-page-side { | |||
transition: top 150ms ease-out; | |||
} | |||
.projects-page-content { | |||
transition: padding-top 150ms ease-out; | |||
} | |||
.projects-topbar-items { | |||
display: flex; | |||
align-items: center; |
@@ -60,6 +60,7 @@ download_verb=Download | |||
duplications=Duplications | |||
edit=Edit | |||
events=Events | |||
explore=Explore | |||
false=False | |||
favorite=Favorite | |||
file=File | |||
@@ -605,6 +606,7 @@ issues.to_navigate_issue_locations=to navigate issue locations | |||
issues.to_switch_flows=to switch flows | |||
issues.leak_period=Leak Period | |||
issues.my_issues=My Issues | |||
issues.no_my_issues=There are no issues assigned to you. | |||
#------------------------------------------------------------------------------ |