From 1be92f5c67d0b8fdd1b7c1c0d45cdd4835579e39 Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Wed, 3 Aug 2022 16:39:27 +0200 Subject: [PATCH] SONAR-16760 [891731] Purpose of link is not clear in context --- .../js/apps/overview/branches/DebtValue.tsx | 24 ++-- .../branches/DrilldownMeasureValue.tsx | 11 +- .../__snapshots__/DebtValue-test.tsx.snap | 2 + .../DrilldownMeasureValue-test.tsx.snap | 1 + .../apps/overview/components/IssueLabel.tsx | 24 ++-- .../overview/components/MeasurementLabel.tsx | 61 +++++----- .../__snapshots__/IssueLabel-test.tsx.snap | 8 ++ .../MeasurementLabel-test.tsx.snap | 7 ++ .../js/components/shared/DrilldownLink.tsx | 109 +++++++++--------- .../resources/org/sonar/l10n/core.properties | 3 + 10 files changed, 152 insertions(+), 98 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/overview/branches/DebtValue.tsx b/server/sonar-web/src/main/js/apps/overview/branches/DebtValue.tsx index 32f7311144f..e9219dfb5f7 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/DebtValue.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/DebtValue.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { getLeakValue } from '../../../components/measure/utils'; import DrilldownLink from '../../../components/shared/DrilldownLink'; -import { getLocalizedMetricName, translate } from '../../../helpers/l10n'; +import { getLocalizedMetricName, translate, translateWithParameters } from '../../../helpers/l10n'; import { findMeasure, formatMeasure, localizeMetric } from '../../../helpers/measures'; import { BranchLike } from '../../../types/branch-like'; import { MetricKey } from '../../../types/metrics'; @@ -35,13 +35,18 @@ export interface DebtValueProps { export function DebtValue(props: DebtValueProps) { const { branchLike, component, measures, useDiffMetric = false } = props; - const metric = useDiffMetric ? MetricKey.new_technical_debt : MetricKey.sqale_index; - const measure = findMeasure(measures, metric); + const metricKey = useDiffMetric ? MetricKey.new_technical_debt : MetricKey.sqale_index; + const measure = findMeasure(measures, metricKey); let value; + let metricName; if (measure) { value = useDiffMetric ? getLeakValue(measure) : measure.value; + metricName = getLocalizedMetricName(measure.metric, true); + } else { + metricName = localizeMetric(metricKey); } + const formattedValue = formatMeasure(value, 'WORK_DUR'); return ( <> @@ -49,16 +54,19 @@ export function DebtValue(props: DebtValueProps) { ) : ( - {formatMeasure(value, 'WORK_DUR')} + metric={metricKey}> + {formattedValue} )} - - {measure ? getLocalizedMetricName(measure.metric, true) : localizeMetric(metric)} - + {metricName} ); } diff --git a/server/sonar-web/src/main/js/apps/overview/branches/DrilldownMeasureValue.tsx b/server/sonar-web/src/main/js/apps/overview/branches/DrilldownMeasureValue.tsx index 700d5b681db..87846f3f6c9 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/DrilldownMeasureValue.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/DrilldownMeasureValue.tsx @@ -19,8 +19,8 @@ */ import * as React from 'react'; import DrilldownLink from '../../../components/shared/DrilldownLink'; -import { getLocalizedMetricName } from '../../../helpers/l10n'; -import { findMeasure, formatMeasure } from '../../../helpers/measures'; +import { getLocalizedMetricName, translateWithParameters } from '../../../helpers/l10n'; +import { findMeasure, formatMeasure, localizeMetric } from '../../../helpers/measures'; import { BranchLike } from '../../../types/branch-like'; import { MetricKey } from '../../../types/metrics'; import { Component, MeasureEnhanced } from '../../../types/types'; @@ -37,12 +37,17 @@ export function DrilldownMeasureValue(props: DrilldownMeasureValueProps) { const measure = findMeasure(measures, metric); let content; - if (!measure) { + if (!measure || measure.value === undefined) { content = -; } else { content = ( {value === undefined ? ( ) : ( + to={url}> {formatMeasure(value, 'SHORT_INT')} )} {React.createElement(iconClass, { className: 'big-spacer-left little-spacer-right' })} - {localizeMetric(metric)} + {localizeMetric(metricKey)} {helpTooltip && } ); diff --git a/server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx b/server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx index 9f265a6d1a0..9532e2e18b3 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx @@ -21,8 +21,8 @@ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { getLeakValue } from '../../../components/measure/utils'; import DrilldownLink from '../../../components/shared/DrilldownLink'; -import { translate } from '../../../helpers/l10n'; -import { findMeasure, formatMeasure } from '../../../helpers/measures'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { findMeasure, formatMeasure, localizeMetric } from '../../../helpers/measures'; import { BranchLike } from '../../../types/branch-like'; import { Component, MeasureEnhanced } from '../../../types/types'; import { @@ -51,34 +51,34 @@ export default class MeasurementLabel extends React.Component { if (!measure) { return translate(labelKey); - } else { - const value = useDiffMetric ? getLeakValue(measure) : measure.value; - - return ( - - {formatMeasure(value, 'SHORT_INT')} - - ) - }} - /> - ); } + + const value = useDiffMetric ? getLeakValue(measure) : measure.value; + + return ( + + {formatMeasure(value, 'SHORT_INT')} + + ) + }} + /> + ); }; render() { const { branchLike, centered, component, measures, type, useDiffMetric = false } = this.props; const iconClass = getMeasurementIconClass(type); - const metric = getMeasurementMetricKey(type, useDiffMetric); - const measure = findMeasure(measures, metric); + const metricKey = getMeasurementMetricKey(type, useDiffMetric); + const measure = findMeasure(measures, metricKey); let value; if (measure) { @@ -95,13 +95,22 @@ export default class MeasurementLabel extends React.Component { } const icon = React.createElement(iconClass, { size: 'big', value: Number(value) }); + const formattedValue = formatMeasure(value, 'PERCENT', { + decimals: 2, + omitExtraDecimalZeros: true + }); const link = ( - {formatMeasure(value, 'PERCENT', { decimals: 2, omitExtraDecimalZeros: true })} + metric={metricKey}> + {formattedValue} ); const label = this.getLabelText(); diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap index 07600034dc3..ebba3879584 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap @@ -3,6 +3,7 @@ exports[`should render correctly for bugs 1`] = ` > = { - blocker_violations: { resolved: 'false', severities: 'BLOCKER' }, - new_blocker_violations: { resolved: 'false', severities: 'BLOCKER' }, - critical_violations: { resolved: 'false', severities: 'CRITICAL' }, - new_critical_violations: { resolved: 'false', severities: 'CRITICAL' }, - major_violations: { resolved: 'false', severities: 'MAJOR' }, - new_major_violations: { resolved: 'false', severities: 'MAJOR' }, - minor_violations: { resolved: 'false', severities: 'MINOR' }, - new_minor_violations: { resolved: 'false', severities: 'MINOR' }, - info_violations: { resolved: 'false', severities: 'INFO' }, - new_info_violations: { resolved: 'false', severities: 'INFO' }, - open_issues: { resolved: 'false', statuses: 'OPEN' }, - reopened_issues: { resolved: 'false', statuses: 'REOPENED' }, - confirmed_issues: { resolved: 'false', statuses: 'CONFIRMED' }, - false_positive_issues: { resolutions: 'FALSE-POSITIVE' }, - code_smells: { resolved: 'false', types: 'CODE_SMELL' }, - new_code_smells: { resolved: 'false', types: 'CODE_SMELL' }, - bugs: { resolved: 'false', types: 'BUG' }, - new_bugs: { resolved: 'false', types: 'BUG' }, - vulnerabilities: { resolved: 'false', types: 'VULNERABILITY' }, - new_vulnerabilities: { resolved: 'false', types: 'VULNERABILITY' } + [MetricKey.blocker_violations]: { resolved: 'false', severities: 'BLOCKER' }, + [MetricKey.new_blocker_violations]: { resolved: 'false', severities: 'BLOCKER' }, + [MetricKey.critical_violations]: { resolved: 'false', severities: 'CRITICAL' }, + [MetricKey.new_critical_violations]: { resolved: 'false', severities: 'CRITICAL' }, + [MetricKey.major_violations]: { resolved: 'false', severities: 'MAJOR' }, + [MetricKey.new_major_violations]: { resolved: 'false', severities: 'MAJOR' }, + [MetricKey.minor_violations]: { resolved: 'false', severities: 'MINOR' }, + [MetricKey.new_minor_violations]: { resolved: 'false', severities: 'MINOR' }, + [MetricKey.info_violations]: { resolved: 'false', severities: 'INFO' }, + [MetricKey.new_info_violations]: { resolved: 'false', severities: 'INFO' }, + [MetricKey.open_issues]: { resolved: 'false', statuses: 'OPEN' }, + [MetricKey.reopened_issues]: { resolved: 'false', statuses: 'REOPENED' }, + [MetricKey.confirmed_issues]: { resolved: 'false', statuses: 'CONFIRMED' }, + [MetricKey.false_positive_issues]: { resolutions: 'FALSE-POSITIVE' }, + [MetricKey.code_smells]: { resolved: 'false', types: 'CODE_SMELL' }, + [MetricKey.new_code_smells]: { resolved: 'false', types: 'CODE_SMELL' }, + [MetricKey.bugs]: { resolved: 'false', types: 'BUG' }, + [MetricKey.new_bugs]: { resolved: 'false', types: 'BUG' }, + [MetricKey.vulnerabilities]: { resolved: 'false', types: 'VULNERABILITY' }, + [MetricKey.new_vulnerabilities]: { resolved: 'false', types: 'VULNERABILITY' } }; interface Props { + ariaLabel?: string; branchLike?: BranchLike; children?: React.ReactNode; className?: string; @@ -83,7 +85,7 @@ interface Props { export default class DrilldownLink extends React.PureComponent { isIssueMeasure = () => { - return ISSUE_MEASURES.indexOf(this.props.metric) !== -1; + return ISSUE_MEASURES.indexOf(this.props.metric as MetricKey) !== -1; }; propsToIssueParams = () => { @@ -99,14 +101,16 @@ export default class DrilldownLink extends React.PureComponent { }; renderIssuesLink = () => { - const url = getComponentIssuesUrl(this.props.component, { + const { ariaLabel, className, component, children, branchLike } = this.props; + + const url = getComponentIssuesUrl(component, { ...this.propsToIssueParams(), - ...getBranchLikeQuery(this.props.branchLike) + ...getBranchLikeQuery(branchLike) }); return ( - - {this.props.children} + + {children} ); }; @@ -115,16 +119,17 @@ export default class DrilldownLink extends React.PureComponent { if (this.isIssueMeasure()) { return this.renderIssuesLink(); } + const { ariaLabel, className, metric, component, children, branchLike } = this.props; const url = getComponentDrilldownUrl({ - componentKey: this.props.component, - metric: this.props.metric, - branchLike: this.props.branchLike, + componentKey: component, + metric, + branchLike, listView: true }); return ( - - {this.props.children} + + {children} ); } 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 7b8d1526bb7..33b62b45f1b 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3117,6 +3117,9 @@ overview.started_on_x=Started on {0} overview.previous_analysis_on_x=Previous analysis on {0} overview.on_new_code=On New Code overview.on_new_code_long=Conditions on New Code +overview.see_list_of_x_y_issues=See the list of {0} {1} +overview.see_more_details_on_x_of_y=See more details on {0} of {1} +overview.see_more_details_on_x_y=See more details on {0} {1} overview.about_this_portfolio=About This Portfolio overview.about_this_project.APP=About This Application overview.about_this_project.TRK=About This Project -- 2.39.5