From: Grégoire Aubert Date: Fri, 26 May 2017 14:25:49 +0000 (+0200) Subject: SONAR-9245 Add all leak facets X-Git-Tag: 6.5-M1~83 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=eb029461e77fbb1f7a9dde462512d88fc65d46b4;p=sonarqube.git SONAR-9245 Add all leak facets --- 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 b6ebb70b8e6..85d9184784d 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 @@ -22,9 +22,20 @@ import React from 'react'; import { Link } from 'react-router'; import FavoriteFilterContainer from './FavoriteFilterContainer'; import LanguagesFilterContainer from '../filters/LanguagesFilterContainer'; -import PageSidebarOverall from './PageSidebarOverall'; +import CoverageFilter from '../filters/CoverageFilter'; +import DuplicationsFilter from '../filters/DuplicationsFilter'; +import MaintainabilityFilter from '../filters/MaintainabilityFilter'; +import NewCoverageFilter from '../filters/NewCoverageFilter'; +import NewDuplicationsFilter from '../filters/NewDuplicationsFilter'; +import NewMaintainabilityFilter from '../filters/NewMaintainabilityFilter'; +import NewReliabilityFilter from '../filters/NewReliabilityFilter'; +import NewSecurityFilter from '../filters/NewSecurityFilter'; +import NewSizeFilter from '../filters/NewSizeFilter'; import QualityGateFilter from '../filters/QualityGateFilter'; +import ReliabilityFilter from '../filters/ReliabilityFilter'; +import SecurityFilter from '../filters/SecurityFilter'; import SearchFilterContainer from '../filters/SearchFilterContainer'; +import SizeFilter from '../filters/SizeFilter'; import TagsFilterContainer from '../filters/TagsFilterContainer'; import { translate } from '../../../helpers/l10n'; @@ -49,6 +60,7 @@ export default function PageSidebar({ const isLeakView = view === 'leak'; const basePathName = organization ? `/organizations/${organization.key}/projects` : '/projects'; const pathname = basePathName + (isFavorite ? '/favorite' : ''); + const facetProps = { query, isFavorite, organization }; let linkQuery: ?{ view: string, visualization?: string }; if (view !== 'overall') { @@ -72,13 +84,27 @@ export default function PageSidebar({ }

{translate('filters')}

- + - - {!isLeakView && - } - - + + {!isLeakView && [ + , + , + , + , + , + + ]} + {isLeakView && [ + , + , + , + , + , + + ]} + + ); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageSidebarOverall.js b/server/sonar-web/src/main/js/apps/projects/components/PageSidebarOverall.js deleted file mode 100644 index 67e782ae469..00000000000 --- a/server/sonar-web/src/main/js/apps/projects/components/PageSidebarOverall.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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. - */ -//@flow -import React from 'react'; -import CoverageFilter from '../filters/CoverageFilter'; -import DuplicationsFilter from '../filters/DuplicationsFilter'; -import SizeFilter from '../filters/SizeFilter'; -import ReliabilityFilter from '../filters/ReliabilityFilter'; -import SecurityFilter from '../filters/SecurityFilter'; -import MaintainabilityFilter from '../filters/MaintainabilityFilter'; - -type Props = { - isFavorite: boolean, - organization?: { key: string }, - query: { [string]: string } -}; - -export default function PageSidebarOverall({ query, isFavorite, organization }: Props) { - return ( -
- - - - - - -
- ); -} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js index e55404cfe42..2b9698e7c19 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js @@ -47,7 +47,7 @@ export default function ProjectCardLeakMeasures({ measures }: Props) { /> -
+
{translate('metric.new_bugs.name')}
@@ -64,7 +64,7 @@ export default function ProjectCardLeakMeasures({ measures }: Props) { />
-
+
{translate('metric.new_vulnerabilities.name')}
@@ -81,7 +81,7 @@ export default function ProjectCardLeakMeasures({ measures }: Props) { />
-
+
{translate('metric.new_code_smells.name')}
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js index 219a6650903..7a1c8a31c6c 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js @@ -109,7 +109,7 @@ export default function ProjectCardOverallMeasures({ measures }: Props) { {measures['ncloc'] != null &&
-
+
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PageSidebar-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PageSidebar-test.js.snap index 3bfd6952c23..fdbeb7ed11b 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PageSidebar-test.js.snap +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PageSidebar-test.js.snap @@ -57,6 +57,55 @@ exports[`should render \`leak\` view correctly 1`] = ` } } /> + + + + + + - + + + + +
+
{this.props.header} {this.renderOptions()} {this.props.footer} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/IssuesFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/IssuesFilter.js index a287639d59c..52e52bc92a2 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/IssuesFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/IssuesFilter.js @@ -20,17 +20,18 @@ import React from 'react'; import FilterContainer from './FilterContainer'; import FilterHeader from './FilterHeader'; -import SortingFilter from './SortingFilter'; import Rating from '../../../components/ui/Rating'; import { translate } from '../../../helpers/l10n'; export default class IssuesFilter extends React.PureComponent { static propTypes = { - property: React.PropTypes.string.isRequired, - name: React.PropTypes.string.isRequired, - query: React.PropTypes.object.isRequired, + className: React.PropTypes.string, + headerDetail: React.PropTypes.element, isFavorite: React.PropTypes.bool, - organization: React.PropTypes.object + organization: React.PropTypes.object, + name: React.PropTypes.string.isRequired, + property: React.PropTypes.string.isRequired, + query: React.PropTypes.object.isRequired }; getFacetValueForOption(facet, option) { @@ -52,6 +53,7 @@ export default class IssuesFilter extends React.PureComponent { return ( - + {this.props.headerDetail} } /> diff --git a/server/sonar-web/src/main/js/apps/projects/filters/NewCoverageFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/NewCoverageFilter.js new file mode 100644 index 00000000000..24f24ce2706 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/NewCoverageFilter.js @@ -0,0 +1,25 @@ +/* + * 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 React from 'react'; +import CoverageFilter from './CoverageFilter'; + +export default function NewCoverageFilter(props) { + return ; +} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/NewDuplicationsFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/NewDuplicationsFilter.js new file mode 100644 index 00000000000..98754c93080 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/NewDuplicationsFilter.js @@ -0,0 +1,25 @@ +/* + * 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 React from 'react'; +import DuplicationsFilter from './DuplicationsFilter'; + +export default function NewDuplicationsFilter(props) { + return ; +} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/NewMaintainabilityFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/NewMaintainabilityFilter.js new file mode 100644 index 00000000000..b501476a25f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/NewMaintainabilityFilter.js @@ -0,0 +1,42 @@ +/* + * 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 React from 'react'; +import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; +import IssuesFilter from './IssuesFilter'; +import { translate } from '../../../helpers/l10n'; + +export default function NewMaintainabilityFilter(props) { + return ( + + {'('} + + {translate('metric.code_smells.name')} + {' )'} + + } + name="Maintainability" + property="new_maintainability" + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/NewReliabilityFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/NewReliabilityFilter.js new file mode 100644 index 00000000000..0dbb948a577 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/NewReliabilityFilter.js @@ -0,0 +1,39 @@ +/* + * 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 React from 'react'; +import BugIcon from '../../../components/icons-components/BugIcon'; +import IssuesFilter from './IssuesFilter'; +import { translate } from '../../../helpers/l10n'; + +export default function NewReliabilityFilter(props) { + return ( + + {'('}{translate('metric.bugs.name')}{' )'} + + } + name="Reliability" + property="new_reliability" + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/NewSecurityFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/NewSecurityFilter.js new file mode 100644 index 00000000000..7d2e64e74c7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/NewSecurityFilter.js @@ -0,0 +1,42 @@ +/* + * 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 React from 'react'; +import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon'; +import IssuesFilter from './IssuesFilter'; +import { translate } from '../../../helpers/l10n'; + +export default function NewSecurityFilter(props) { + return ( + + {'('} + + {translate('metric.vulnerabilities.name')} + {' )'} + + } + name="Security" + property="new_security" + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/NewSizeFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/NewSizeFilter.js new file mode 100644 index 00000000000..c672d6c0ce4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/NewSizeFilter.js @@ -0,0 +1,86 @@ +/* + * 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 React from 'react'; +import FilterContainer from './FilterContainer'; +import FilterHeader from './FilterHeader'; +import SortingFilter from './SortingFilter'; +import { translate } from '../../../helpers/l10n'; +import { getSizeRatingLabel } from '../../../helpers/ratings'; + +export default class NewSizeFilter extends React.PureComponent { + static propTypes = { + className: React.PropTypes.string, + query: React.PropTypes.object.isRequired, + isFavorite: React.PropTypes.bool, + organization: React.PropTypes.object, + property: React.PropTypes.string + }; + + static defaultProps = { + property: 'new_lines' + }; + + getFacetValueForOption(facet, option) { + const map = [ + '*-1000.0', + '1000.0-10000.0', + '10000.0-100000.0', + '100000.0-500000.0', + '500000.0-*' + ]; + return facet[map[option - 1]]; + } + + renderOption(option) { + return ( + + {getSizeRatingLabel(option)} + + ); + } + + render() { + return ( + + + + } + /> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/SizeFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/SizeFilter.js index c9cb96b15bc..aedd2d966cd 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/SizeFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/SizeFilter.js @@ -27,12 +27,16 @@ import { getSizeRatingLabel, getSizeRatingAverageValue } from '../../../helpers/ export default class SizeFilter extends React.PureComponent { static propTypes = { + className: React.PropTypes.string, query: React.PropTypes.object.isRequired, isFavorite: React.PropTypes.bool, - organization: React.PropTypes.object + organization: React.PropTypes.object, + property: React.PropTypes.string }; - property = 'size'; + static defaultProps = { + property: 'size' + }; getFacetValueForOption(facet, option) { const map = [ @@ -56,23 +60,11 @@ export default class SizeFilter extends React.PureComponent { ); } - renderSort = () => { - return ( - - ); - }; - render() { return ( error => { parseError(error).then(message => dispatch(addGlobalErrorMessage(message))); dispatch(updateState({ loading: false })); @@ -124,6 +136,13 @@ const defineMetrics = query => { } }; +const defineFacets = query => { + if (query.view === 'leak') { + return LEAK_FACETS; + } + return FACETS; +}; + const fetchProjectMeasures = (projects, query) => dispatch => { if (!projects.length) { return Promise.resolve(); @@ -193,7 +212,7 @@ export const fetchProjects = (query, isFavorite, organization) => dispatch => { const ps = query.view === 'visualizations' ? PAGE_SIZE_VISUALIZATIONS : PAGE_SIZE; const data = convertToQueryData(query, isFavorite, organization, { ps, - facets: FACETS.join(), + facets: defineFacets(query).join(), f: 'analysisDate,leakPeriodDate' }); return searchProjects(data).then(onReceiveProjects(dispatch, query), onFail(dispatch)); diff --git a/server/sonar-web/src/main/js/apps/projects/store/facetsDuck.js b/server/sonar-web/src/main/js/apps/projects/store/facetsDuck.js index 953fcaf4101..f47b8d67471 100644 --- a/server/sonar-web/src/main/js/apps/projects/store/facetsDuck.js +++ b/server/sonar-web/src/main/js/apps/projects/store/facetsDuck.js @@ -24,14 +24,20 @@ import { mapMetricToProperty } from './utils'; const CUMULATIVE_FACETS = [ 'reliability', + 'new_reliability', 'security', + 'new_security', 'maintainability', + 'new_maintainability', 'coverage', + 'new_coverage', 'duplications', - 'size' + 'new_duplications', + 'size', + 'new_lines' ]; -const REVERSED_FACETS = ['coverage']; +const REVERSED_FACETS = ['coverage', 'new_coverage']; const mapFacetValues = values => { const map = {}; diff --git a/server/sonar-web/src/main/js/apps/projects/store/utils.js b/server/sonar-web/src/main/js/apps/projects/store/utils.js index 0316f71ab7f..13db6e4c7cb 100644 --- a/server/sonar-web/src/main/js/apps/projects/store/utils.js +++ b/server/sonar-web/src/main/js/apps/projects/store/utils.js @@ -57,11 +57,17 @@ const getVisualization = value => { export const parseUrlQuery = urlQuery => ({ gate: getAsLevel(urlQuery['gate']), reliability: getAsNumericRating(urlQuery['reliability']), + new_reliability: getAsNumericRating(urlQuery['new_reliability']), security: getAsNumericRating(urlQuery['security']), + new_security: getAsNumericRating(urlQuery['new_security']), maintainability: getAsNumericRating(urlQuery['maintainability']), + new_maintainability: getAsNumericRating(urlQuery['new_maintainability']), coverage: getAsNumericRating(urlQuery['coverage']), + new_coverage: getAsNumericRating(urlQuery['new_coverage']), duplications: getAsNumericRating(urlQuery['duplications']), + new_duplications: getAsNumericRating(urlQuery['new_duplications']), size: getAsNumericRating(urlQuery['size']), + new_lines: getAsNumericRating(urlQuery['new_lines']), languages: getAsArray(urlQuery['languages'], getAsString), tags: getAsArray(urlQuery['tags'], getAsString), search: getAsString(urlQuery['search']), @@ -73,11 +79,17 @@ export const parseUrlQuery = urlQuery => ({ export const mapMetricToProperty = metricKey => { const map = { reliability_rating: 'reliability', + new_reliability_rating: 'new_reliability', security_rating: 'security', + new_security_rating: 'new_security', sqale_rating: 'maintainability', + new_maintainability_rating: 'new_maintainability', coverage: 'coverage', + new_coverage: 'new_coverage', duplicated_lines_density: 'duplications', + new_duplicated_lines_density: 'new_duplications', ncloc: 'size', + new_lines: 'new_lines', alert_status: 'gate', languages: 'languages', tags: 'tags', @@ -89,11 +101,17 @@ export const mapMetricToProperty = metricKey => { export const mapPropertyToMetric = property => { const map = { reliability: 'reliability_rating', + new_reliability: 'new_reliability_rating', security: 'security_rating', + new_security: 'new_security_rating', maintainability: 'sqale_rating', + new_maintainability: 'new_maintainability_rating', coverage: 'coverage', + new_coverage: 'new_coverage', duplications: 'duplicated_lines_density', + new_duplications: 'new_duplicated_lines_density', size: 'ncloc', + new_lines: 'new_lines', gate: 'alert_status', languages: 'languages', tags: 'tags', @@ -110,57 +128,70 @@ const convertIssuesRating = (metric, rating) => { } }; -const convertCoverage = coverage => { +const convertCoverage = (metric, coverage) => { switch (coverage) { case 1: - return mapPropertyToMetric('coverage') + ' >= 80'; + return metric + ' >= 80'; case 2: - return mapPropertyToMetric('coverage') + ' < 80'; + return metric + ' < 80'; case 3: - return mapPropertyToMetric('coverage') + ' < 70'; + return metric + ' < 70'; case 4: - return mapPropertyToMetric('coverage') + ' < 50'; + return metric + ' < 50'; case 5: - return mapPropertyToMetric('coverage') + ' < 30'; + return metric + ' < 30'; default: return ''; } }; -const convertDuplications = duplications => { +const convertDuplications = (metric, duplications) => { switch (duplications) { case 1: - return mapPropertyToMetric('duplications') + ' < 3'; + return metric + ' < 3'; case 2: - return mapPropertyToMetric('duplications') + ' >= 3'; + return metric + ' >= 3'; case 3: - return mapPropertyToMetric('duplications') + ' >= 5'; + return metric + ' >= 5'; case 4: - return mapPropertyToMetric('duplications') + ' >= 10'; + return metric + ' >= 10'; case 5: - return mapPropertyToMetric('duplications') + ' >= 20'; + return metric + ' >= 20'; default: return ''; } }; -const convertSize = size => { +const convertSize = (metric, size) => { switch (size) { case 1: - return mapPropertyToMetric('size') + ' < 1000'; + return metric + ' < 1000'; case 2: - return mapPropertyToMetric('size') + ' >= 1000'; + return metric + ' >= 1000'; case 3: - return mapPropertyToMetric('size') + ' >= 10000'; + return metric + ' >= 10000'; case 4: - return mapPropertyToMetric('size') + ' >= 100000'; + return metric + ' >= 100000'; case 5: - return mapPropertyToMetric('size') + ' >= 500000'; + return metric + ' >= 500000'; default: return ''; } }; +const convertArrayMetric = (metric, items) => { + if (!Array.isArray(items) || items.length < 2) { + return metric + ' = ' + items; + } + return `${metric} IN (${items.join(', ')})`; +}; + +const pushMetricToArray = (query, property, conditionsArray, convertFunction) => { + if (query[property] != null) { + conditionsArray.push(convertFunction(mapPropertyToMetric(property), query[property])); + } +}; + export const convertToFilter = (query, isFavorite) => { const conditions = []; @@ -172,34 +203,30 @@ export const convertToFilter = (query, isFavorite) => { conditions.push(mapPropertyToMetric('gate') + ' = ' + query['gate']); } - if (query['coverage'] != null) { - conditions.push(convertCoverage(query['coverage'])); - } + ['coverage', 'new_coverage'].forEach(property => + pushMetricToArray(query, property, conditions, convertCoverage) + ); - if (query['duplications'] != null) { - conditions.push(convertDuplications(query['duplications'])); - } + ['duplications', 'new_duplications'].forEach(property => + pushMetricToArray(query, property, conditions, convertDuplications) + ); - if (query['size'] != null) { - conditions.push(convertSize(query['size'])); - } + ['size', 'new_lines'].forEach(property => + pushMetricToArray(query, property, conditions, convertSize) + ); - ['reliability', 'security', 'maintainability'].forEach(property => { - if (query[property] != null) { - conditions.push(convertIssuesRating(mapPropertyToMetric(property), query[property])); - } - }); + [ + 'reliability', + 'security', + 'maintainability', + 'new_reliability', + 'new_security', + 'new_maintainability' + ].forEach(property => pushMetricToArray(query, property, conditions, convertIssuesRating)); - ['languages', 'tags'].forEach(property => { - const items = query[property]; - if (items != null) { - if (!Array.isArray(items) || items.length < 2) { - conditions.push(mapPropertyToMetric(property) + ' = ' + items); - } else { - conditions.push(`${mapPropertyToMetric(property)} IN (${items.join(', ')})`); - } - } - }); + ['languages', 'tags'].forEach(property => + pushMetricToArray(query, property, conditions, convertArrayMetric) + ); if (query['search'] != null) { conditions.push(`${mapPropertyToMetric('search')} = "${query['search']}"`); diff --git a/server/sonar-web/src/main/less/components/search-navigator.less b/server/sonar-web/src/main/less/components/search-navigator.less index e01e2dc742a..23c8a7b3ff4 100644 --- a/server/sonar-web/src/main/less/components/search-navigator.less +++ b/server/sonar-web/src/main/less/components/search-navigator.less @@ -74,12 +74,21 @@ .search-navigator-facet-box { background-color: @barBackgroundColor; font-size: @baseFontSize; + + &.leak-facet-box { + background-color: @leakBackgroundColor; + border: 1px solid @leakBorderColor; + } } -.search-navigator-facet-box:not(.hidden) + .search-navigator-facet-box { +.search-navigator-facet-box:not(.hidden):not(.leak-facet-box) + .search-navigator-facet-box:not(.leak-facet-box) { border-top: 1px solid @barBorderColor; } +.leak-facet-box:not(.hidden) + .leak-facet-box { + border-top: none; +} + .search-navigator-facet-box-collapsed { background-color: transparent; @@ -198,32 +207,46 @@ background-color: @red; color: #fff; } +} - &.active { - border: 1px solid @blue; - padding: 3px 5px; - background-color: @lightBlue; - text-decoration: none; +.leak-facet-box .search-navigator-facet { + .facet-name { + background-color: @leakBackgroundColor; + } - .facet-name { - background-color: @lightBlue; + .facet-stat { + background-color: @leakBackgroundColor; + + &:before { + background-image: linear-gradient(to right, fade(@leakBackgroundColor, 0%), @leakBackgroundColor 75%); } + } +} - .facet-stat { - border-color: @blue; - background-color: @lightBlue; - top: -1px; - right: -1px; +.search-navigator-facet.active { + border: 1px solid @blue; + padding: 3px 5px; + background-color: @lightBlue; + text-decoration: none; - &:before { - background-image: linear-gradient(to right, fade(@lightBlue, 0%), @lightBlue 75%); - } - } + .facet-name { + background-color: @lightBlue; + } - .facet-toggle { - display: inline; + .facet-stat { + border-color: @blue; + background-color: @lightBlue; + top: -1px; + right: -1px; + + &:before { + background-image: linear-gradient(to right, fade(@lightBlue, 0%), @lightBlue 75%); } } + + .facet-toggle { + display: inline; + } } .search-navigator-facet-indent { @@ -309,6 +332,10 @@ border-bottom: none; color: @baseFontColor; font-weight: 600; + + & > .note { + font-weight: 400; + } } .search-navigator-facet-header-button { diff --git a/server/sonar-web/src/main/less/variables.less b/server/sonar-web/src/main/less/variables.less index 7f0a91caf8e..ca3a1a87f0d 100644 --- a/server/sonar-web/src/main/less/variables.less +++ b/server/sonar-web/src/main/less/variables.less @@ -89,7 +89,8 @@ @issueBackgroundColor: #ffeaea; @issueBorderColor: desaturate(darken(@issueBackgroundColor, 40%), 30%); - +@leakBackgroundColor: #fbf3d5; +@leakBorderColor: #eae3c7; /* * Sizes @@ -168,7 +169,6 @@ - /* * Page */ 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 047896dc5dd..3099a7c1931 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1939,6 +1939,7 @@ severity.INFO.description=Neither a bug nor a quality flaw. Just a finding. #------------------------------------------------------------------------------ metric_domain.Size=Size +metric_domain.new_size=New Lines metric_domain.Tests=Tests metric_domain.Integration Tests=Integration Tests metric_domain.Complexity=Complexity