@@ -0,0 +1,42 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2024 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 { Note } from 'design-system'; | |||
import React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { formatMeasure } from '~sonar-aligned/helpers/measures'; | |||
import { MetricKey, MetricType } from '~sonar-aligned/types/metrics'; | |||
import { findMeasure } from '../../../helpers/measures'; | |||
import { MeasureEnhanced } from '../../../types/types'; | |||
interface Props { | |||
measures: MeasureEnhanced[]; | |||
overallMetric: MetricKey; | |||
} | |||
export default function AfterMergeNote({ measures, overallMetric }: Readonly<Props>) { | |||
const afterMergeValue = findMeasure(measures, overallMetric)?.value; | |||
return afterMergeValue ? ( | |||
<Note className="sw-mt-2 sw-body-xs sw-inline-block"> | |||
<strong className="sw-mr-1">{formatMeasure(afterMergeValue, MetricType.Percent)}</strong> | |||
<FormattedMessage id="component_measures.facet_category.overall_category.estimated" /> | |||
</Note> | |||
) : null; | |||
} |
@@ -17,14 +17,9 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { LinkHighlight, LinkStandalone } from '@sonarsource/echoes-react'; | |||
import classNames from 'classnames'; | |||
import { | |||
ContentLink, | |||
CoverageIndicator, | |||
DuplicationsIndicator, | |||
LightLabel, | |||
TextError, | |||
} from 'design-system'; | |||
import { CoverageIndicator, DuplicationsIndicator, LightLabel, TextError } from 'design-system'; | |||
import * as React from 'react'; | |||
import { FormattedMessage, useIntl } from 'react-intl'; | |||
import { To } from 'react-router-dom'; | |||
@@ -34,6 +29,7 @@ import { duplicationRatingConverter, getLeakValue } from '../../../components/me | |||
import { translate, translateWithParameters } from '../../../helpers/l10n'; | |||
import { findMeasure, localizeMetric } from '../../../helpers/measures'; | |||
import { getComponentDrilldownUrl } from '../../../helpers/urls'; | |||
import { isPullRequest } from '../../../sonar-aligned/helpers/branch-like'; | |||
import { BranchLike } from '../../../types/branch-like'; | |||
import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates'; | |||
import { MeasureEnhanced } from '../../../types/types'; | |||
@@ -43,6 +39,7 @@ import { | |||
getConditionRequiredLabel, | |||
getMeasurementMetricKey, | |||
} from '../utils'; | |||
import AfterMergeNote from './AfterMergeNote'; | |||
import MeasuresCard from './MeasuresCard'; | |||
interface Props { | |||
@@ -55,6 +52,7 @@ interface Props { | |||
conditions: QualityGateStatusConditionEnhanced[]; | |||
conditionMetric: MetricKey; | |||
linesMetric: MetricKey; | |||
overallConditionMetric?: MetricKey; | |||
useDiffMetric?: boolean; | |||
showRequired?: boolean; | |||
} | |||
@@ -71,6 +69,7 @@ export default function MeasuresCardPercent( | |||
measures, | |||
conditions, | |||
conditionMetric, | |||
overallConditionMetric, | |||
linesMetric, | |||
useDiffMetric = false, | |||
showRequired = false, | |||
@@ -131,7 +130,8 @@ export default function MeasuresCardPercent( | |||
id={linesLabel} | |||
values={{ | |||
link: ( | |||
<ContentLink | |||
<LinkStandalone | |||
highlight={LinkHighlight.Default} | |||
aria-label={translateWithParameters( | |||
'overview.see_more_details_on_x_y', | |||
linesValue ?? '0', | |||
@@ -141,12 +141,15 @@ export default function MeasuresCardPercent( | |||
to={linesUrl} | |||
> | |||
{formatMeasure(linesValue ?? '0', MetricType.ShortInteger)} | |||
</ContentLink> | |||
</LinkStandalone> | |||
), | |||
}} | |||
/> | |||
</LightLabel> | |||
</div> | |||
{overallConditionMetric && isPullRequest(branchLike) && ( | |||
<AfterMergeNote measures={measures} overallMetric={overallConditionMetric} /> | |||
)} | |||
</MeasuresCard> | |||
); | |||
} |
@@ -71,6 +71,7 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>) | |||
})} | |||
conditions={conditions} | |||
conditionMetric={MetricKey.new_coverage} | |||
overallConditionMetric={MetricKey.coverage} | |||
linesMetric={MetricKey.new_lines_to_cover} | |||
measures={measures} | |||
showRequired | |||
@@ -106,6 +107,7 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>) | |||
})} | |||
conditions={conditions} | |||
conditionMetric={MetricKey.new_duplicated_lines_density} | |||
overallConditionMetric={MetricKey.duplicated_lines_density} | |||
linesMetric={MetricKey.new_lines} | |||
measures={measures} | |||
useDiffMetric |
@@ -51,6 +51,9 @@ jest.mock('../../../../api/measures', () => { | |||
mockMeasure({ | |||
metric: MetricKey.new_coverage, | |||
}), | |||
mockMeasure({ | |||
metric: MetricKey.coverage, | |||
}), | |||
mockMeasure({ | |||
metric: MetricKey.duplicated_lines, | |||
}), | |||
@@ -70,6 +73,7 @@ jest.mock('../../../../api/measures', () => { | |||
}, | |||
metrics: [ | |||
mockMetric({ key: MetricKey.new_coverage }), | |||
mockMetric({ key: MetricKey.coverage }), | |||
mockMetric({ key: MetricKey.duplicated_lines }), | |||
mockMetric({ key: MetricKey.new_lines, type: MetricType.ShortInteger }), | |||
mockMetric({ key: MetricKey.new_bugs, type: MetricType.Integer }), | |||
@@ -181,6 +185,9 @@ it('should render correctly for a passed QG', async () => { | |||
expect(screen.getByLabelText('overview.quality_gate_x.overview.gate.OK')).toBeInTheDocument(); | |||
expect(screen.getByText('metric.new_lines.name')).toBeInTheDocument(); | |||
expect( | |||
screen.getByText('component_measures.facet_category.overall_category.estimated'), | |||
).toBeInTheDocument(); | |||
expect(screen.getByText(/overview.last_analysis_x/)).toBeInTheDocument(); | |||
}); | |||
@@ -3912,8 +3912,7 @@ overview.quality_gate.duplications=Duplications | |||
overview.new_coverage.on_x_new_lines=On {link} New Lines to cover. | |||
overview.coverage.on_x_new_lines=On {link} lines to cover. | |||
overview.new_duplicated_lines_density.on_x_new_lines=On {link} New Lines. | |||
overview.duplicated_lines_density.on_x_new_lines=On {link} lines. | |||
overview.quality_gate.x_estimated_after_merge={value} Estimated after merge | |||
overview.duplicated_lines_density.on_x_new_lines=On {link} lines. | |||
overview.quality_gate.require_fixing={count, plural, one {requires} other {require}} fixing | |||
overview.quality_gate.require_reviewing={count, plural, one {requires} other {require}} reviewing | |||
overview.quality_gate.required_x=Required {operator} {requirement} |