瀏覽代碼

SONAR-9245 Update sorting select for leak in projects page

tags/6.5-M1
Grégoire Aubert 7 年之前
父節點
當前提交
8f72ff7117

+ 3
- 1
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}
/>

+ 5
- 2
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}

+ 14
- 7
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}
/>

+ 2
- 5
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>
);
}

+ 24
- 0
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();
});

+ 13
- 3
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();
});

+ 19
- 0
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"
/>
`;

+ 30
- 54
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",
},
]

+ 8
- 0
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;

+ 6
- 6
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 = {

+ 7
- 11
sonar-core/src/main/resources/org/sonar/l10n/core.properties 查看文件

@@ -869,7 +869,8 @@ projects.perspective=Perspective
projects.sort_by=Sort by
projects.sort_ascending=Result sorted in ascending order
projects.sort_descending=Result sorted in descending order
projects.sorting.name=Name (default)
projects.sorting.default=default
projects.sorting.name=Name
projects.sorting.analysis_date=Last analysis date
projects.sorting.reliability=Reliability
projects.sorting.security=Security
@@ -877,16 +878,11 @@ projects.sorting.maintainability=Maintainability
projects.sorting.coverage=Coverage
projects.sorting.duplications=Duplications
projects.sorting.size=Size
projects.sorting.new_reliability=Reliability on New Code
projects.sorting.new_security=Security on New Code
projects.sorting.new_maintainability=Maintainability on New Code
projects.sorting.new_coverage=Coverage on New Code
projects.sorting.new_duplications=Duplications on New Lines
projects.sorting.new_reliability.short=Reliability
projects.sorting.new_security.short=Security
projects.sorting.new_maintainability.short=Maintainability
projects.sorting.new_coverage.short=Coverage
projects.sorting.new_duplications.short=Duplications
projects.sorting.new_reliability=Reliability
projects.sorting.new_security=Security
projects.sorting.new_maintainability=Maintainability
projects.sorting.new_coverage=Coverage
projects.sorting.new_duplications=Duplications
projects.sorting.new_lines=New Lines
projects.sorting.on_new_code=on New Code
projects.sorting.on_new_lines=on New Lines

Loading…
取消
儲存