diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2016-03-08 14:47:18 +0100 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2016-03-09 14:12:33 +0100 |
commit | 89de9611b4b455a58ca22170fc46c38350816e87 (patch) | |
tree | a30b5c10e018a2a52848cc689791cc70ebbaec5c /server | |
parent | 8549b6143656ddd868948584ffd99c021805d9a4 (diff) | |
download | sonarqube-89de9611b4b455a58ca22170fc46c38350816e87.tar.gz sonarqube-89de9611b4b455a58ca22170fc46c38350816e87.zip |
SONAR-7410 Display related measures alongside with selected one on the "Measures" page
Diffstat (limited to 'server')
6 files changed, 148 insertions, 26 deletions
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/LanguageDistribution.js b/server/sonar-web/src/main/js/apps/component-measures/components/LanguageDistribution.js new file mode 100644 index 00000000000..ea0e9db68ba --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/LanguageDistribution.js @@ -0,0 +1,71 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 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 _ from 'underscore'; +import React from 'react'; + +import { Histogram } from '../../../components/charts/histogram'; +import { formatMeasure } from '../../../helpers/measures'; +import { getLanguages } from '../../../api/languages'; +import { translate } from '../../../helpers/l10n'; + + +export default class LanguageDistribution extends React.Component { + componentDidMount () { + this.requestLanguages(); + } + + requestLanguages () { + getLanguages().then(languages => this.setState({ languages })); + } + + getLanguageName (langKey) { + if (this.state && this.state.languages) { + const lang = _.findWhere(this.state.languages, { key: langKey }); + return lang ? lang.name : translate('unknown'); + } else { + return langKey; + } + } + + cutLanguageName (name) { + return name.length > 10 ? `${name.substr(0, 7)}...` : name; + } + + render () { + let data = this.props.distribution.split(';').map((point, index) => { + const tokens = point.split('='); + return { x: parseInt(tokens[1], 10), y: index, value: tokens[0] }; + }); + + data = _.sortBy(data, d => -d.x); + + const yTicks = data.map(point => this.getLanguageName(point.value)).map(this.cutLanguageName); + const yValues = data.map(point => formatMeasure(point.x, 'SHORT_INT')); + + return ( + <Histogram data={data} + yTicks={yTicks} + yValues={yValues} + barsWidth={10} + height={data.length * 25} + padding={[0, 60, 0, 80]}/> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js index fa15d267c52..2ffc441f163 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js @@ -65,19 +65,33 @@ export default class MeasureDetails extends React.Component { fetchMeasure () { const { metricKey } = this.props.params; const { component } = this.context; + const metrics = [metricKey]; + + if (metricKey === 'ncloc') { + metrics.push('ncloc_language_distribution'); + } + + if (metricKey === 'function_complexity') { + metrics.push('function_complexity_distribution'); + } + + if (metricKey === 'file_complexity') { + metrics.push('file_complexity_distribution'); + } getMeasuresAndMeta( component.key, - [metricKey], + metrics, { additionalFields: 'periods' } ).then(r => { - const measures = r.component.measures; - - if (this.mounted && measures.length === 1) { - const measure = enhanceWithLeak(measures[0]); + if (this.mounted) { + const measures = enhanceWithLeak(r.component.measures); + const measure = measures.find(measure => measure.metric === metricKey); + const secondaryMeasure = measures.find(measure => measure.metric !== metricKey); this.setState({ measure, + secondaryMeasure, periods: r.periods }); } @@ -85,7 +99,7 @@ export default class MeasureDetails extends React.Component { } render () { - const { measure, periods } = this.state; + const { measure, secondaryMeasure, periods } = this.state; if (!measure) { return <Spinner/>; @@ -101,6 +115,7 @@ export default class MeasureDetails extends React.Component { <MeasureDetailsHeader measure={measure} metric={this.metric} + secondaryMeasure={secondaryMeasure} leakPeriodLabel={leakPeriodLabel}/> {measure && ( diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js index 93d0e8b58f3..737074afe9a 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js @@ -19,12 +19,14 @@ */ import React from 'react'; +import LanguageDistribution from './LanguageDistribution'; +import { ComplexityDistribution } from '../../overview/components/complexity-distribution'; import { formatLeak } from '../utils'; import { formatMeasure } from '../../../helpers/measures'; import { translateWithParameters } from '../../../helpers/l10n'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -export default function MeasureDetailsHeader ({ measure, metric, leakPeriodLabel }) { +export default function MeasureDetailsHeader ({ measure, metric, secondaryMeasure, leakPeriodLabel }) { const leakPeriodTooltip = translateWithParameters('overview.leak_period_x', leakPeriodLabel); return ( @@ -49,6 +51,24 @@ export default function MeasureDetailsHeader ({ measure, metric, leakPeriodLabel {formatLeak(measure.leak, metric)} </div> )} + + {secondaryMeasure && secondaryMeasure.metric === 'ncloc_language_distribution' && ( + <div className="measure-details-secondary"> + <LanguageDistribution distribution={secondaryMeasure.value}/> + </div> + )} + + {secondaryMeasure && secondaryMeasure.metric === 'function_complexity_distribution' && ( + <div className="measure-details-secondary"> + <ComplexityDistribution distribution={secondaryMeasure.value} of="function"/> + </div> + )} + + {secondaryMeasure && secondaryMeasure.metric === 'file_complexity_distribution' && ( + <div className="measure-details-secondary"> + <ComplexityDistribution distribution={secondaryMeasure.value} of="file"/> + </div> + )} </div> </TooltipsContainer> </header> diff --git a/server/sonar-web/src/main/js/apps/component-measures/styles.css b/server/sonar-web/src/main/js/apps/component-measures/styles.css index e09866b9c43..185c82761c7 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/styles.css +++ b/server/sonar-web/src/main/js/apps/component-measures/styles.css @@ -73,25 +73,35 @@ .measure-details-value { font-size: 24px; - font-weight: 300; } .measure-details-value-absolute { display: inline-block; + vertical-align: middle; padding: 5px 0; + font-weight: 300; } .measure-details-value-leak { display: inline-block; + vertical-align: middle; padding: 4px 10px; border: 1px solid #eae3c7; background-color: #fbf3d5; + font-weight: 300; } .measure-details-value-absolute + .measure-details-value-leak { margin-left: 20px; } +.measure-details-secondary { + display: inline-block; + vertical-align: middle; + width: 260px; + margin-left: 20px; +} + .measure-details-drilldown { margin-top: 20px; } diff --git a/server/sonar-web/src/main/less/components/graphics.less b/server/sonar-web/src/main/less/components/graphics.less index dbe699f6ff0..b78984ad29c 100644 --- a/server/sonar-web/src/main/less/components/graphics.less +++ b/server/sonar-web/src/main/less/components/graphics.less @@ -338,3 +338,27 @@ text.max-results-reached-message { .bubble-chart-tick-y { text-anchor: end; } + +/* + * Bar Chart + */ +.bar-chart { +} + +.bar-chart-bar { + fill: @blue; +} + +.bar-chart-tick { + fill: @secondFontColor; + font-size: 12px; + text-anchor: middle; +} + +.histogram-tick { + text-anchor: end; +} + +.histogram-value { + text-anchor: start; +} diff --git a/server/sonar-web/src/main/less/pages/overview.less b/server/sonar-web/src/main/less/pages/overview.less index e11b40a93c3..b7c14709f08 100644 --- a/server/sonar-web/src/main/less/pages/overview.less +++ b/server/sonar-web/src/main/less/pages/overview.less @@ -422,24 +422,6 @@ svg { position: absolute; } - - .bar-chart-bar { - fill: @blue; - } - - .bar-chart-tick { - fill: @secondFontColor; - font-size: 12px; - text-anchor: middle; - } - - .histogram-tick { - text-anchor: end; - } - - .histogram-value { - text-anchor: start; - } } .overview-timeline { |