]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22216 Add the after merge information in PRs overview
authorMathieu Suen <mathieu.suen@sonarsource.com>
Thu, 16 May 2024 08:44:00 +0000 (10:44 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 16 May 2024 20:02:38 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/overview/components/AfterMergeNote.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/MeasuresCardPercent.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx
sonar-core/src/main/resources/org/sonar/l10n/core.properties

diff --git a/server/sonar-web/src/main/js/apps/overview/components/AfterMergeNote.tsx b/server/sonar-web/src/main/js/apps/overview/components/AfterMergeNote.tsx
new file mode 100644 (file)
index 0000000..9bb4f6f
--- /dev/null
@@ -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;
+}
index a225ca5dfa77b16a44566d1836b1e8c70d01db45..f29fc2801464cf65c88926fe4d2e44e8a6c7794c 100644 (file)
  * 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>
   );
 }
index e1780472c0fc4363b2e7741b6838623e9846b498..101f1cb5cfb4b14685a4d7bdc0d883a02591db68 100644 (file)
@@ -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
index 44478340b694fbfe4f89a69e71d44d49d26e4b75..4ff9d9a9378f27493a5f04473102608c55f80b37 100644 (file)
@@ -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();
 });
 
index 46eb48c9a603eac537d53b0c7d4198f17ebb3de6..824f1bf2c0b606614eb9da31e386cc207ebcf679 100644 (file)
@@ -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}