From c844886cf44799e77093a2df5e0da8196bacb395 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Fri, 15 Jul 2016 17:10:39 +0200 Subject: [PATCH] SONAR-7492 Display an explanation tooltip for rating measures (#1104) --- .../apps/overview/components/OverviewApp.js | 17 ++++++---- .../src/main/js/apps/overview/main/enhance.js | 34 +++++++++++++++++-- .../sonar-web/src/main/js/helpers/measures.js | 21 ++++++++++++ .../WEB-INF/app/views/layouts/_head.html.erb | 3 +- .../resources/org/sonar/l10n/core.properties | 12 +++++++ 5 files changed, 77 insertions(+), 10 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js index 666d4f8d9ef..836a749bb39 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js @@ -33,6 +33,7 @@ import { getTimeMachineData } from '../../../api/time-machine'; import { enhanceMeasuresWithMetrics } from '../../../helpers/measures'; import { getLeakPeriod } from '../../../helpers/periods'; import { ComponentType } from '../propTypes'; +import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import '../styles.css'; @@ -184,13 +185,15 @@ export default class OverviewApp extends React.Component { measures={measures} periods={periods}/> -
- - - - - -
+ +
+ + + + + +
+
diff --git a/server/sonar-web/src/main/js/apps/overview/main/enhance.js b/server/sonar-web/src/main/js/apps/overview/main/enhance.js index 4c11fa91011..91f3b8a37b4 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/enhance.js +++ b/server/sonar-web/src/main/js/apps/overview/main/enhance.js @@ -31,9 +31,10 @@ import { getPeriodValue, getShortType } from '../../../helpers/measures'; -import { translateWithParameters } from '../../../helpers/l10n'; +import { translateWithParameters, translate } from '../../../helpers/l10n'; import { getPeriodDate } from '../../../helpers/periods'; import { getComponentIssuesUrl } from '../../../helpers/urls'; +import { getMaintainabilityRatingGrid } from '../../../helpers/measures'; export default function enhance (ComposedComponent) { return class extends React.Component { @@ -131,6 +132,27 @@ export default function enhance (ComposedComponent) { ); } + getMaintainabilityRatingTooltip (rating) { + const maintainabilityGrid = getMaintainabilityRatingGrid(); + const maintainabilityRatingThreshold = + maintainabilityGrid[Math.floor(rating) - 2]; + + console.log(maintainabilityGrid[0]); + + if (rating < 2) { + return translateWithParameters( + 'metric.sqale_rating.tooltip.A', + `${maintainabilityGrid[0]}%`); + } + + const ratingLetter = formatMeasure(rating, 'RATING'); + + return translateWithParameters( + 'metric.sqale_rating.tooltip', + ratingLetter, + `${maintainabilityRatingThreshold}%`); + } + renderRating (metricKey) { const { component, measures } = this.props; const measure = measures.find(measure => measure.metric.key === metricKey); @@ -139,8 +161,16 @@ export default function enhance (ComposedComponent) { return null; } + const ratingLetter = formatMeasure(measure.value, 'RATING'); + + const title = metricKey === 'sqale_rating' ? + this.getMaintainabilityRatingTooltip(measure.value) : + translate('metric', metricKey, 'tooltip', ratingLetter); + return ( -
+
diff --git a/server/sonar-web/src/main/js/helpers/measures.js b/server/sonar-web/src/main/js/helpers/measures.js index c965c1577a6..a3e181e04cb 100644 --- a/server/sonar-web/src/main/js/helpers/measures.js +++ b/server/sonar-web/src/main/js/helpers/measures.js @@ -367,3 +367,24 @@ function shortDurationVariationFormatter (value) { const formatted = shortDurationFormatter(value); return formatted[0] !== '-' ? '+' + formatted : formatted; } + + +let maintainabilityRatingGrid; +export function getMaintainabilityRatingGrid () { + if (maintainabilityRatingGrid) { + return maintainabilityRatingGrid; + } + + const str = window.SS['sonar.technicalDebt.ratingGrid']; + const numbers = str.split(',') + .map(s => parseFloat(s)) + .filter(n => !isNaN(n)); + + if (numbers.length === 4) { + maintainabilityRatingGrid = numbers; + } else { + maintainabilityRatingGrid = [0, 0, 0, 0]; + } + + return maintainabilityRatingGrid; +} diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb index 30673cc211b..afd65ce9196 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb @@ -33,7 +33,8 @@ enableGravatar: <%= configuration('sonar.lf.enableGravatar', true) %>, gravatarServerUrl: '<%= configuration('sonar.lf.gravatarServerUrl') %>' }, - updateCenterActive: <%= configuration('sonar.updatecenter.activate', true) %> + updateCenterActive: <%= configuration('sonar.updatecenter.activate', true) %>, + 'sonar.technicalDebt.ratingGrid': '<%= configuration('sonar.technicalDebt.ratingGrid', "0.05,0.1,0.2,0.5") %>' }; 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 8ff19c3be41..c2ed6ed763c 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2589,6 +2589,11 @@ metric.reliability.description=Reliability metric.reliability.name=Reliability metric.reliability_rating.description=Reliability rating metric.reliability_rating.name=Reliability Rating +metric.reliability_rating.tooltip.A=Reliability rating is A, because there are no bugs. +metric.reliability_rating.tooltip.B=Reliability rating is B, because there is at least one minor bug. +metric.reliability_rating.tooltip.C=Reliability rating is C, because there is at least one major bug. +metric.reliability_rating.tooltip.D=Reliability rating is D, because there is at least one critical bug. +metric.reliability_rating.tooltip.E=Reliability rating is E, because there is at least one blocker bug. metric.reliability_remediation_effort.description=Reliability Remediation Effort metric.reliability_remediation_effort.name=Reliability Remediation Effort metric.reopened_issues.description=Reopened issues @@ -2601,6 +2606,11 @@ metric.rfc_distribution.description=Class distribution /RFC metric.rfc_distribution.name=Class Distribution / RFC metric.security_rating.description=Security rating metric.security_rating.name=Security Rating +metric.security_rating.tooltip.A=Security rating is A, because there are no vulnerabilities. +metric.security_rating.tooltip.B=Security rating is B, because there is at least one minor vulnerability. +metric.security_rating.tooltip.C=Security rating is C, because there is at least one major vulnerability. +metric.security_rating.tooltip.D=Security rating is D, because there is at least one critical vulnerability. +metric.security_rating.tooltip.E=Security rating is E, because there is at least one blocker vulnerability. metric.security_remediation_effort.description=Security remediation effort metric.security_remediation_effort.name=Security Remediation Effort metric.skipped_tests.abbreviation=Skipped UTs @@ -2615,6 +2625,8 @@ metric.sqale_index.name=Technical Debt metric.sqale_index.short_name=Effort metric.sqale_rating.description=A-to-E rating based on the technical debt ratio metric.sqale_rating.name=Maintainability Rating +metric.sqale_rating.tooltip=Maintainability rating is {0}, because the technical debt ratio is greater than {1} +metric.sqale_rating.tooltip.A=Maintainability rating is A, because the technical debt ratio is less than {0} metric.statements.abbreviation=Stmts metric.statements.description=Number of statements metric.statements.name=Statements -- 2.39.5