diff options
Diffstat (limited to 'server/sonar-web/src/main/js')
10 files changed, 124 insertions, 78 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 3adb8c5e0e8..dd440f83927 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 @@ -38,7 +38,8 @@ type Props = { optionBarOpen: boolean, optionBarToggle: (open: boolean) => void, organization?: { key: string }, - router: { push: ({ pathname: string, query?: {} }) => void } + router: { push: ({ pathname: string, query?: {} }) => void }, + user?: { isLoggedIn: boolean } }; type State = { @@ -132,6 +133,7 @@ export default class AllProjects extends React.PureComponent { onToggleOptionBar={this.props.optionBarToggle} open={optionBarOpen} selectedSort={selectedSort} + user={this.props.user} view={view} visualization={visualization} /> 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 ada472b4beb..b076abcb98d 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 @@ -33,6 +33,7 @@ type Props = { projects: Array<*>, projectsAppState: { loading: boolean, total?: number }, selectedSort: string, + user?: { isLoggedIn: boolean }, view: string, visualization?: string }; @@ -47,18 +48,19 @@ export default class ProjectsOptionBar extends React.PureComponent { }; renderSortingSelect() { - const { projectsAppState, projects, view } = this.props; + const { projectsAppState, projects, user, view } = this.props; const limitReached = projects != null && projectsAppState.total != null && projects.length < projectsAppState.total; - + const defaultOption = user && user.isLoggedIn ? 'name' : 'analysis_date'; if (view === 'visualizations' && !limitReached) { return ( <Tooltip overlay={translate('projects.sort.disabled')}> <div> <ProjectsSortingSelect className="projects-topbar-item js-projects-sorting-select disabled" + defaultOption={defaultOption} onChange={this.props.onSortChange} selectedSort={this.props.selectedSort} view={this.props.view} @@ -70,6 +72,7 @@ export default class ProjectsOptionBar extends React.PureComponent { return ( <ProjectsSortingSelect className="projects-topbar-item js-projects-sorting-select" + defaultOption={defaultOption} onChange={this.props.onSortChange} selectedSort={this.props.selectedSort} view={this.props.view} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js index 4a5556bd91d..51d6f1fdd5e 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js @@ -19,6 +19,7 @@ */ // @flow import React from 'react'; +import { sortBy } from 'lodash'; import Select from 'react-select'; import ProjectsSortingSelectOption from './ProjectsSortingSelectOption'; import SortAscIcon from '../../../components/icons-components/SortAscIcon'; @@ -27,13 +28,14 @@ import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; import { SORTING_METRICS, SORTING_LEAK_METRICS, parseSorting } from '../utils'; -export type Option = { label: string, value: string, complement?: string, short?: string }; +export type Option = { label: string, value: string, class?: string, short?: string }; type Props = { className?: string, onChange: (sort: string, desc: boolean) => void, selectedSort: string, - view: string + view: string, + defaultOption: string }; type State = { @@ -58,11 +60,16 @@ export default class ProjectsSortingSelect extends React.PureComponent { getOptions = () => { const sortMetrics = this.props.view === 'leak' ? SORTING_LEAK_METRICS : SORTING_METRICS; - return sortMetrics.map((opt: { value: string, complement?: string }) => ({ + return sortBy( + sortMetrics, + opt => (opt.value === this.props.defaultOption ? 0 : 1) + ).map((opt: { value: string, class?: string }) => ({ value: opt.value, - label: translate('projects.sorting', opt.value), - complement: opt.complement && translate('projects.sorting', opt.complement), - short: opt.complement && translate('projects.sorting', opt.value, 'short') + label: translate('projects.sorting', opt.value) + + (opt.value === this.props.defaultOption + ? ` (${translate('projects.sorting.default')})` + : ''), + class: opt.class })); }; @@ -84,8 +91,8 @@ export default class ProjectsSortingSelect extends React.PureComponent { className="little-spacer-left input-large" clearable={false} onChange={this.handleSortChange} - options={this.getOptions()} optionComponent={ProjectsSortingSelectOption} + options={this.getOptions()} searchable={false} value={this.state.sortValue} /> diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js index f3613f1153e..9789a3d30fb 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js @@ -19,6 +19,7 @@ */ //@flow import React from 'react'; +import classNames from 'classnames'; import type { Option } from './ProjectsSortingSelect'; type Props = { @@ -54,16 +55,12 @@ export default class ProjectsSortingSelectOption extends React.PureComponent { const { option } = this.props; return ( <div - className={this.props.className} + className={classNames(this.props.className, option.class)} onMouseDown={this.handleMouseDown} onMouseEnter={this.handleMouseEnter} onMouseMove={this.handleMouseMove} title={option.label}> {option.short ? option.short : this.props.children} - {option.complement && - <div className="pull-right text-muted-2"> - {option.complement} - </div>} </div> ); } 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 446bf98b57a..14d16176c63 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 @@ -35,6 +35,7 @@ it('should render option bar open', () => { visualization="risk" projects={[1, 2, 3]} projectsAppState={{ total: 3 }} + user={{ isLoggedIn: true }} /> ) ).toMatchSnapshot(); @@ -52,3 +53,26 @@ it('should call close method correctly', () => { click(wrapper.find('.projects-topbar-button')); expect(toggle.mock.calls).toMatchSnapshot(); }); + +it('should render switch the default sorting option for anonymous users', () => { + expect( + shallow( + <ProjectsOptionBar + open={true} + view="overall" + visualization="risk" + user={{ isLoggedIn: true }} + /> + ).find('ProjectsSortingSelect') + ).toMatchSnapshot(); + expect( + shallow( + <ProjectsOptionBar + open={true} + view="leak" + visualization="risk" + user={{ isLoggedIn: false }} + /> + ).find('ProjectsSortingSelect') + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelect-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelect-test.js index 472558d0085..4906bf180b2 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelect-test.js +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectsSortingSelect-test.js @@ -22,17 +22,27 @@ import { shallow } from 'enzyme'; import ProjectsSortingSelect from '../ProjectsSortingSelect'; it('should render correctly for overall view', () => { - expect(shallow(<ProjectsSortingSelect selectedSort="name" view="overall" />)).toMatchSnapshot(); + expect( + shallow(<ProjectsSortingSelect selectedSort="name" view="overall" defaultOption="name" />) + ).toMatchSnapshot(); }); it('should render correctly for leak view', () => { expect( - shallow(<ProjectsSortingSelect selectedSort="new_coverage" view="leak" />) + shallow( + <ProjectsSortingSelect + selectedSort="new_coverage" + view="leak" + defaultOption="analysis_date" + /> + ) ).toMatchSnapshot(); }); it('should handle the descending sort direction', () => { expect( - shallow(<ProjectsSortingSelect selectedSort="-vulnerability" view="overall" />) + shallow( + <ProjectsSortingSelect selectedSort="-vulnerability" view="overall" defaultOption="name" /> + ) ).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 12099c9db00..15051129d68 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 @@ -39,6 +39,7 @@ exports[`should render disabled sorting options for visualizations 1`] = ` <div> <ProjectsSortingSelect className="projects-topbar-item js-projects-sorting-select disabled" + defaultOption="analysis_date" view="visualizations" /> </div> @@ -74,6 +75,7 @@ exports[`should render option bar closed 1`] = ` /> <ProjectsSortingSelect className="projects-topbar-item js-projects-sorting-select" + defaultOption="analysis_date" view="overall" /> </div> @@ -108,6 +110,7 @@ exports[`should render option bar open 1`] = ` /> <ProjectsSortingSelect className="projects-topbar-item js-projects-sorting-select" + defaultOption="name" view="leak" /> </div> @@ -115,3 +118,19 @@ exports[`should render option bar open 1`] = ` </div> </div> `; + +exports[`should render switch the default sorting option for anonymous users 1`] = ` +<ProjectsSortingSelect + className="projects-topbar-item js-projects-sorting-select" + defaultOption="name" + view="overall" +/> +`; + +exports[`should render switch the default sorting option for anonymous users 2`] = ` +<ProjectsSortingSelect + className="projects-topbar-item js-projects-sorting-select" + defaultOption="analysis_date" + view="leak" +/> +`; diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelect-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelect-test.js.snap index c5ef95acbd7..7a004599bfb 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelect-test.js.snap +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsSortingSelect-test.js.snap @@ -40,51 +40,43 @@ exports[`should handle the descending sort direction 1`] = ` options={ Array [ Object { - "complement": undefined, - "label": "projects.sorting.name", - "short": undefined, + "class": undefined, + "label": "projects.sorting.name (projects.sorting.default)", "value": "name", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.analysis_date", - "short": undefined, "value": "analysis_date", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.reliability", - "short": undefined, "value": "reliability", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.security", - "short": undefined, "value": "security", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.maintainability", - "short": undefined, "value": "maintainability", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.coverage", - "short": undefined, "value": "coverage", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.duplications", - "short": undefined, "value": "duplications", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.size", - "short": undefined, "value": "size", }, ] @@ -157,51 +149,43 @@ exports[`should render correctly for leak view 1`] = ` options={ Array [ Object { - "complement": undefined, - "label": "projects.sorting.name", - "short": undefined, - "value": "name", + "class": undefined, + "label": "projects.sorting.analysis_date (projects.sorting.default)", + "value": "analysis_date", }, Object { - "complement": undefined, - "label": "projects.sorting.analysis_date", - "short": undefined, - "value": "analysis_date", + "class": undefined, + "label": "projects.sorting.name", + "value": "name", }, Object { - "complement": "projects.sorting.on_new_code", + "class": "projects-leak-sorting-option", "label": "projects.sorting.new_reliability", - "short": "projects.sorting.new_reliability.short", "value": "new_reliability", }, Object { - "complement": "projects.sorting.on_new_code", + "class": "projects-leak-sorting-option", "label": "projects.sorting.new_security", - "short": "projects.sorting.new_security.short", "value": "new_security", }, Object { - "complement": "projects.sorting.on_new_code", + "class": "projects-leak-sorting-option", "label": "projects.sorting.new_maintainability", - "short": "projects.sorting.new_maintainability.short", "value": "new_maintainability", }, Object { - "complement": "projects.sorting.on_new_code", + "class": "projects-leak-sorting-option", "label": "projects.sorting.new_coverage", - "short": "projects.sorting.new_coverage.short", "value": "new_coverage", }, Object { - "complement": "projects.sorting.on_new_lines", + "class": "projects-leak-sorting-option", "label": "projects.sorting.new_duplications", - "short": "projects.sorting.new_duplications.short", "value": "new_duplications", }, Object { - "complement": undefined, + "class": "projects-leak-sorting-option", "label": "projects.sorting.new_lines", - "short": undefined, "value": "new_lines", }, ] @@ -274,51 +258,43 @@ exports[`should render correctly for overall view 1`] = ` options={ Array [ Object { - "complement": undefined, - "label": "projects.sorting.name", - "short": undefined, + "class": undefined, + "label": "projects.sorting.name (projects.sorting.default)", "value": "name", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.analysis_date", - "short": undefined, "value": "analysis_date", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.reliability", - "short": undefined, "value": "reliability", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.security", - "short": undefined, "value": "security", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.maintainability", - "short": undefined, "value": "maintainability", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.coverage", - "short": undefined, "value": "coverage", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.duplications", - "short": undefined, "value": "duplications", }, Object { - "complement": undefined, + "class": undefined, "label": "projects.sorting.size", - "short": undefined, "value": "size", }, ] 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 aeffc580da6..f9b1b627502 100644 --- a/server/sonar-web/src/main/js/apps/projects/styles.css +++ b/server/sonar-web/src/main/js/apps/projects/styles.css @@ -112,6 +112,14 @@ border: 1px solid #eae3c7; } +.projects-leak-sorting-option { + background-color: #fbf3d5; + margin-bottom: 2px; +} + +.projects-leak-sorting-option.is-focused { + background-color: #eae3c7; +} .project-card-measures .project-card-measure { width: 120px; diff --git a/server/sonar-web/src/main/js/apps/projects/utils.js b/server/sonar-web/src/main/js/apps/projects/utils.js index 85d898e64a0..008bdf5cb6a 100644 --- a/server/sonar-web/src/main/js/apps/projects/utils.js +++ b/server/sonar-web/src/main/js/apps/projects/utils.js @@ -61,12 +61,12 @@ export const SORTING_METRICS = [ export const SORTING_LEAK_METRICS = [ { value: 'name' }, { value: 'analysis_date' }, - { value: 'new_reliability', complement: 'on_new_code' }, - { value: 'new_security', complement: 'on_new_code' }, - { value: 'new_maintainability', complement: 'on_new_code' }, - { value: 'new_coverage', complement: 'on_new_code' }, - { value: 'new_duplications', complement: 'on_new_lines' }, - { value: 'new_lines' } + { value: 'new_reliability', class: 'projects-leak-sorting-option' }, + { value: 'new_security', class: 'projects-leak-sorting-option' }, + { value: 'new_maintainability', class: 'projects-leak-sorting-option' }, + { value: 'new_coverage', class: 'projects-leak-sorting-option' }, + { value: 'new_duplications', class: 'projects-leak-sorting-option' }, + { value: 'new_lines', class: 'projects-leak-sorting-option' } ]; export const SORTING_SWITCH = { |