diff options
8 files changed, 101 insertions, 13 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js index f1f83563352..fefc5f19801 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js +++ b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js @@ -21,7 +21,7 @@ import React from 'react'; import Helmet from 'react-helmet'; import PageHeaderContainer from './PageHeaderContainer'; -import ProjectsOptionBar from './ProjectsOptionBar'; +import ProjectsOptionBarContainer from './ProjectsOptionBarContainer'; import ProjectsListContainer from './ProjectsListContainer'; import ProjectsListFooterContainer from './ProjectsListFooterContainer'; import PageSidebar from './PageSidebar'; @@ -129,7 +129,7 @@ export default class AllProjects extends React.PureComponent { <div> <Helmet title={translate('projects.page')} /> - <ProjectsOptionBar + <ProjectsOptionBarContainer onPerspectiveChange={this.handlePerspectiveChange} onSortChange={this.handleSortChange} onToggleOptionBar={this.handleOptionBarToggle} diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js b/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js index 302ee1941ff..9771b00f497 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js +++ b/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js @@ -54,7 +54,7 @@ export default function PageSidebar({ visualization }: Props) { const isFiltered = Object.keys(query) - .filter(key => key !== 'view' && key !== 'visualization') + .filter(key => !['view', 'visualization', 'sort'].includes(key)) .some(key => query[key] != null); const isLeakView = view === 'leak'; const basePathName = organization ? `/organizations/${organization.key}/projects` : '/projects'; diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBar.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBar.js index e48872ff96e..14a0b01f4b2 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBar.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBar.js @@ -21,14 +21,18 @@ import React from 'react'; import classNames from 'classnames'; import CloseIcon from '../../../components/icons-components/CloseIcon'; +import Tooltip from '../../../components/controls/Tooltip'; import PerspectiveSelect from './PerspectiveSelect'; import ProjectsSortingSelect from './ProjectsSortingSelect'; +import { translate } from '../../../helpers/l10n'; type Props = { onPerspectiveChange: ({ view: string, visualization?: string }) => void, onSortChange: (sort: string, desc: boolean) => void, onToggleOptionBar: boolean => void, open: boolean, + projects: Array<*>, + projectsAppState: { loading: boolean, total?: number }, selectedSort: string, view: string, visualization?: string @@ -43,6 +47,37 @@ export default class ProjectsOptionBar extends React.PureComponent { this.props.onToggleOptionBar(false); }; + renderSortingSelect() { + const { projectsAppState, projects, view } = this.props; + const limitReached = + projects != null && + projectsAppState.total != null && + projects.length < projectsAppState.total; + + if (view === 'visualizations' && !limitReached) { + return ( + <Tooltip overlay={translate('projects.sort.disabled')}> + <div> + <ProjectsSortingSelect + className="projects-topbar-item js-projects-sorting-select disabled" + onChange={this.props.onSortChange} + selectedSort={this.props.selectedSort} + view={this.props.view} + /> + </div> + </Tooltip> + ); + } + return ( + <ProjectsSortingSelect + className="projects-topbar-item js-projects-sorting-select" + onChange={this.props.onSortChange} + selectedSort={this.props.selectedSort} + view={this.props.view} + /> + ); + } + render() { const { open } = this.props; return ( @@ -58,12 +93,7 @@ export default class ProjectsOptionBar extends React.PureComponent { view={this.props.view} visualization={this.props.visualization} /> - <ProjectsSortingSelect - className="projects-topbar-item js-projects-sorting-select" - onChange={this.props.onSortChange} - selectedSort={this.props.selectedSort} - view={this.props.view} - /> + {this.renderSortingSelect()} </div> </div> </div> diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBarContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBarContainer.js new file mode 100644 index 00000000000..a58605b2355 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsOptionBarContainer.js @@ -0,0 +1,29 @@ +/* + * 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 { connect } from 'react-redux'; +import ProjectsOptionBar from './ProjectsOptionBar'; +import { getProjects, getProjectsAppState } from '../../../store/rootReducer'; + +const mapStateToProps = state => ({ + projects: getProjects(state), + projectsAppState: getProjectsAppState(state) +}); + +export default connect(mapStateToProps)(ProjectsOptionBar); diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectOptionBar-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectOptionBar-test.js index 338395a6b84..5b08f5d644e 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectOptionBar-test.js +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectOptionBar-test.js @@ -28,11 +28,19 @@ it('should render option bar closed', () => { it('should render option bar open', () => { expect( - shallow(<ProjectsOptionBar open={true} view="leak" visualization="risk" />) + shallow( + <ProjectsOptionBar + open={true} + view="leak" + visualization="risk" + projects={[1, 2, 3]} + projectsAppState={{ total: 3 }} + /> + ) ).toMatchSnapshot(); }); -it.skip('should not render sorting options for visualizations', () => { +it('should render disabled sorting options for visualizations', () => { expect( shallow(<ProjectsOptionBar open={true} view="visualizations" visualization="coverage" />) ).toMatchSnapshot(); diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectOptionBar-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectOptionBar-test.js.snap index 27dff385bd9..5b5ca60dce6 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectOptionBar-test.js.snap +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectOptionBar-test.js.snap @@ -8,7 +8,7 @@ Array [ ] `; -exports[`should not render sorting options for visualizations 1`] = ` +exports[`should render disabled sorting options for visualizations 1`] = ` <div className="projects-topbar" > @@ -26,10 +26,21 @@ exports[`should not render sorting options for visualizations 1`] = ` className="projects-topbar-actions-inner" > <PerspectiveSelect - className="projects-topbar-item" + className="projects-topbar-item js-projects-perspective-select" view="visualizations" visualization="coverage" /> + <Tooltip + overlay="projects.sort.disabled" + placement="bottom" + > + <div> + <ProjectsSortingSelect + className="projects-topbar-item js-projects-sorting-select disabled" + view="visualizations" + /> + </div> + </Tooltip> </div> </div> </div> diff --git a/server/sonar-web/src/main/js/apps/projects/styles.css b/server/sonar-web/src/main/js/apps/projects/styles.css index 5bb422126c2..11b1a7b4665 100644 --- a/server/sonar-web/src/main/js/apps/projects/styles.css +++ b/server/sonar-web/src/main/js/apps/projects/styles.css @@ -43,6 +43,15 @@ padding: 0 24px; } +.projects-topbar-item.disabled { + cursor: not-allowed; + opacity: 0.4; +} + +.projects-topbar-item.disabled * { + pointer-events: none !important; +} + .projects-topbar-button { box-sizing: border-box; float: right; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 2a0e497caa8..7d1f3bb714c 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -910,6 +910,7 @@ projects.facets.quality_gate=Quality Gate projects.facets.languages=Languages projects.facets.new_lines=New Lines projects.facets.tags=Tags +projects.sort.disabled=Disabled because sorting cannot affect the displayed result with the current project selection. projects.sort.name=by name projects.sort.reliability=by reliability (best first) projects.sort.-reliability=by reliability (worst first) |