]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21380 migrate QG status in measures to new UI
authorJeremy Davis <jeremy.davis@sonarsource.com>
Wed, 31 Jan 2024 14:21:10 +0000 (15:21 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 1 Feb 2024 20:02:46 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx
server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.tsx
server/sonar-web/src/main/js/apps/component-measures/sidebar/SubnavigationMeasureValue.tsx
server/sonar-web/src/main/js/components/measure/Measure.tsx
server/sonar-web/src/main/js/components/measure/__tests__/MeasureIndicator-test.tsx
server/sonar-web/src/main/js/components/measure/__tests__/__snapshots__/MeasureIndicator-test.tsx.snap

index d3d4a052100f741eea7152d11fede49b9383ee50..c4e45eab0705b50a13615351df3ad1454935cab1 100644 (file)
@@ -280,7 +280,7 @@ class ComponentMeasuresApp extends React.PureComponent<Props, State> {
       <LargeCenteredLayout id="component-measures" className="sw-pt-8">
         <Suggestions suggestions="component_measures" />
         <Helmet defer={false} title={translate('layout.measures')} />
-        <PageContentFontWrapper>
+        <PageContentFontWrapper className="sw-body-sm">
           <Spinner className="my-10 sw-flex sw-content-center" loading={this.state.loading} />
 
           {measures.length > 0 ? (
index 8066803a613c0964bbdeaeb7ed1d91ef7210edf6..0d7849925274d78a271c4ce9377fc226fd222904 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import classNames from 'classnames';
-import { Highlight, Link, MetricsLabel, MetricsRatingBadge } from 'design-system';
+import { Link, MetricsLabel, MetricsRatingBadge } from 'design-system';
 import * as React from 'react';
 import LanguageDistribution from '../../../components/charts/LanguageDistribution';
 import Tooltip from '../../../components/controls/Tooltip';
@@ -58,36 +58,39 @@ export default function MeasureHeader(props: Props) {
       <div className="sw-flex sw-items-center sw-justify-between sw-gap-4">
         <div className="it__measure-details-metric sw-flex sw-items-center sw-gap-1">
           <strong className="sw-body-md-highlight">{getLocalizedMetricName(metric)}</strong>
-          <Measure
-            className={classNames('it__measure-details-value sw-body-md')}
-            metricKey={metric.key}
-            metricType={metric.type}
-            value={measureValue}
-            ratingComponent={
-              <MetricsRatingBadge
-                label={
-                  measureValue
-                    ? translateWithParameters(
-                        'metric.has_rating_X',
-                        formatMeasure(measureValue, MetricType.Rating),
-                      )
-                    : translate('metric.no_rating')
-                }
-                rating={formatMeasure(measureValue, MetricType.Rating) as MetricsLabel}
-              />
-            }
-          />
+
+          <div className="sw-flex sw-items-center sw-ml-2">
+            <Measure
+              className={classNames('it__measure-details-value sw-body-md')}
+              metricKey={metric.key}
+              metricType={metric.type}
+              value={measureValue}
+              ratingComponent={
+                <MetricsRatingBadge
+                  label={
+                    measureValue
+                      ? translateWithParameters(
+                          'metric.has_rating_X',
+                          formatMeasure(measureValue, MetricType.Rating),
+                        )
+                      : translate('metric.no_rating')
+                  }
+                  rating={formatMeasure(measureValue, MetricType.Rating) as MetricsLabel}
+                />
+              }
+            />
+          </div>
 
           {!isDiff && hasHistory && (
             <Tooltip overlay={translate('component_measures.show_metric_history')}>
-              <Highlight>
+              <span className="sw-ml-4">
                 <Link
-                  className="it__show-history-link  sw-font-semibold sw-ml-4"
+                  className="it__show-history-link sw-font-semibold"
                   to={getMeasureHistoryUrl(component.key, metric.key, branchLike)}
                 >
                   {translate('component_measures.see_metric_history')}
                 </Link>
-              </Highlight>
+              </span>
             </Tooltip>
           )}
         </div>
index 44e9f48de56579fe4e6fb3cd46282a22f5b7e468..3deb76113b33abc85c79affd25854c2b68d00fc6 100644 (file)
@@ -53,6 +53,7 @@ export default function SubnavigationMeasureValue({ measure }: Props) {
         }
         metricKey={measure.metric.key}
         metricType={measure.metric.type}
+        small
         value={value}
       />
     </Note>
index 2747b801004086c864201c941b163b06c2d71884..c665ada3e7956a751cc8bb9f648aad1c2ac8c63c 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 { QualityGateIndicator } from 'design-system';
 import * as React from 'react';
 import Tooltip from '../../components/controls/Tooltip';
-import Level from '../../components/ui/Level';
 import Rating from '../../components/ui/Rating';
+import { translateWithParameters } from '../../helpers/l10n';
 import { formatMeasure } from '../../helpers/measures';
 import { MetricType } from '../../types/metrics';
+import { Status } from '../../types/types';
 import RatingTooltipContent from './RatingTooltipContent';
 
 interface Props {
@@ -49,7 +51,20 @@ export default function Measure({
   }
 
   if (metricType === MetricType.Level) {
-    return <Level className={className} level={value?.toString()} small={small} />;
+    const formatted = formatMeasure(value, MetricType.Level);
+    const ariaLabel = translateWithParameters('overview.quality_gate_x', formatted);
+
+    return (
+      <>
+        <QualityGateIndicator
+          status={(value as Status) ?? 'NONE'}
+          className="sw-mr-2"
+          ariaLabel={ariaLabel}
+          size={small ? 'sm' : 'md'}
+        />
+        <span className={small ? '' : 'sw-body-md'}>{formatted}</span>
+      </>
+    );
   }
 
   if (metricType !== MetricType.Rating) {
index c660710949695bdc28b42e82862c194e68bc27fc..621cf364c11cc3a4432bf8ef59b2c27bf357ca67 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { render, screen } from '@testing-library/react';
 import * as React from 'react';
+import { Status } from '../../../apps/overview/utils';
 import { MetricKey, MetricType } from '../../../types/metrics';
 import MeasureIndicator from '../MeasureIndicator';
 
@@ -32,3 +33,26 @@ it('renders correctly for coverage', () => {
   );
   expect(screen.getByRole('img')).toMatchSnapshot();
 });
+
+it('renders correctly for failed quality gate', () => {
+  const wrapper = render(
+    <MeasureIndicator
+      metricKey={MetricKey.alert_status}
+      metricType={MetricType.Level}
+      small
+      value={Status.ERROR}
+    />,
+  );
+  expect(wrapper.baseElement).toMatchSnapshot();
+});
+
+it('renders correctly for passed quality gate', () => {
+  const wrapper = render(
+    <MeasureIndicator
+      metricKey={MetricKey.alert_status}
+      metricType={MetricType.Level}
+      value={Status.OK}
+    />,
+  );
+  expect(wrapper.baseElement).toMatchSnapshot();
+});
index 41fcb0725e8837076597b5552969b0e97adad555..b088c02d4c2a1755d8e38470b4f0fff5e40e84bc 100644 (file)
@@ -25,3 +25,83 @@ exports[`renders correctly for coverage 1`] = `
   </g>
 </svg>
 `;
+
+exports[`renders correctly for failed quality gate 1`] = `
+<body>
+  <div>
+    <div
+      aria-label="overview.quality_gate_x.ERROR"
+      class="sw-flex sw-justify-center sw-items-center"
+    >
+      <svg
+        class="sw-mr-2"
+        fill="none"
+        height="1rem"
+        role="status"
+        width="1rem"
+        xmlns="http://www.w3.org/2000/svg"
+      >
+        <rect
+          fill="rgb(254,205,202)"
+          height="1rem"
+          rx="2"
+          width="1rem"
+        />
+        <path
+          d="m10.227 5 .871.871-5.227 5.227L5 10.227z"
+          fill="rgb(128,27,20)"
+        />
+        <path
+          d="m11.098 10.227-.871.87L5 5.872 5.87 5z"
+          fill="rgb(128,27,20)"
+        />
+      </svg>
+    </div>
+    <span
+      class=""
+    >
+      ERROR
+    </span>
+  </div>
+</body>
+`;
+
+exports[`renders correctly for passed quality gate 1`] = `
+<body>
+  <div>
+    <div
+      aria-label="overview.quality_gate_x.OK"
+      class="sw-flex sw-justify-center sw-items-center"
+    >
+      <svg
+        class="sw-mr-2"
+        fill="none"
+        height="1.5rem"
+        role="status"
+        width="1.5rem"
+        xmlns="http://www.w3.org/2000/svg"
+      >
+        <rect
+          fill="rgb(209,250,223)"
+          height="1.5rem"
+          rx="2"
+          width="1.5rem"
+        />
+        <path
+          d="m16.95 7.5 1.308 1.307-7.84 7.84-1.308-1.306z"
+          fill="rgb(5,96,58)"
+        />
+        <path
+          d="m11.79 15.34-1.307 1.307-4.484-4.483 1.307-1.306z"
+          fill="rgb(5,96,58)"
+        />
+      </svg>
+    </div>
+    <span
+      class="sw-body-md"
+    >
+      OK
+    </span>
+  </div>
+</body>
+`;