]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22390 Refactor PR summary to similar to overview
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Fri, 14 Jun 2024 15:06:14 +0000 (17:06 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 18 Jun 2024 20:02:41 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/nav/component/branch-like/CurrentBranchLikeMergeInformation.tsx
server/sonar-web/src/main/js/apps/overview/branches/BranchSummaryStyles.tsx
server/sonar-web/src/main/js/apps/overview/branches/FailedConditions.tsx
server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx
server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanelSection.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCard.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx

index d8d7c24da37dbb8548a15f694f8f59c2182badc4..def592a66019d6fcbf3a8a29495756515f938636 100644 (file)
@@ -31,7 +31,7 @@ export function CurrentBranchLikeMergeInformation({
 }: Readonly<CurrentBranchLikeMergeInformationProps>) {
   return (
     <span
-      className="sw-w-[400px] sw-text-ellipsis sw-whitespace-nowrap sw-overflow-hidden sw-flex-shrink sw-min-w-0"
+      className="sw-max-w-[400px] sw-text-ellipsis sw-whitespace-nowrap sw-overflow-hidden sw-flex-shrink sw-min-w-0"
       title={translateWithParameters(
         'branch_like_navigation.for_merge_into_x_from_y.title',
         pullRequest.target,
index 82cfda5f35575d3f76a6e19bafc1bcb021bb45cb..0d4095baf8c1f960c3a8c1244a5a4f08d1f1426f 100644 (file)
@@ -54,6 +54,21 @@ export const StyleMeasuresCard = styled.div`
   }
 `;
 
+export const StyleMeasuresCardRightBorder = styled.div`
+  box-sizing: border-box;
+  position: relative;
+
+  &:not(:last-child):before {
+    content: '';
+    position: absolute;
+    top: 0;
+    right: calc(var(--grids-gaps) / -2);
+    height: 100%;
+    width: 1px;
+    background: ${themeColor('pageBlockBorder')};
+  }
+`;
+
 export const StyledConditionsCard = styled.div`
   box-sizing: border-box;
   position: relative;
index d81e6250b12c048fc91326d015430b6d03a2e59f..223cbf1f8369656b27ee3b9898029631f9814a6d 100644 (file)
@@ -22,15 +22,18 @@ import _ from 'lodash';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
 import { isDiffMetric } from '../../../helpers/measures';
-import { QualityGateStatus } from '../../../types/quality-gates';
-import { QualityGate } from '../../../types/types';
+import { BranchLike } from '../../../types/branch-like';
+import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
+import { Component, QualityGate } from '../../../types/types';
 import ZeroNewIssuesSimplificationGuide from '../components/ZeroNewIssuesSimplificationGuide';
 import QualityGateConditions from './QualityGateConditions';
 
 export interface FailedConditionsProps {
+  branchLike?: BranchLike;
+  component: Pick<Component, 'key'>;
+  failedConditions: QualityGateStatusConditionEnhanced[];
   isApplication?: boolean;
   isNewCode: boolean;
-  qgStatus: QualityGateStatus;
   qualityGate?: QualityGate;
 }
 
@@ -38,9 +41,10 @@ export default function FailedConditions({
   isApplication,
   isNewCode,
   qualityGate,
-  qgStatus,
+  failedConditions,
+  component,
+  branchLike,
 }: FailedConditionsProps) {
-  const { failedConditions, branchLike } = qgStatus;
   const [newCodeFailedConditions, overallFailedConditions] = _.partition(
     failedConditions,
     (condition) => isDiffMetric(condition.metric),
@@ -70,7 +74,7 @@ export default function FailedConditions({
         <ZeroNewIssuesSimplificationGuide qualityGate={qualityGate} />
       )}
       <QualityGateConditions
-        component={qgStatus}
+        component={component}
         branchLike={branchLike}
         failedConditions={isNewCode ? newCodeFailedConditions : overallFailedConditions}
         isBuiltInQualityGate={isNewCode && qualityGate?.isBuiltIn}
index 985cfa72f489c4c570260924763673e944a425e9..fb1dd98d32170da0d69e47f565f3358e715841ec 100644 (file)
@@ -38,8 +38,8 @@ export interface QualityGatePanelProps {
   loading?: boolean;
   qgStatuses?: QualityGateStatus[];
   qualityGate?: QualityGate;
-  showCaycWarningInApp: boolean;
-  showCaycWarningInProject: boolean;
+  showCaycWarningInApp?: boolean;
+  showCaycWarningInProject?: boolean;
   totalFailedConditionLength: number;
 }
 
@@ -51,8 +51,8 @@ export function QualityGatePanel(props: QualityGatePanelProps) {
     qualityGate,
     isNewCode = false,
     totalFailedConditionLength,
-    showCaycWarningInProject,
-    showCaycWarningInApp,
+    showCaycWarningInProject = false,
+    showCaycWarningInApp = false,
   } = props;
 
   if (qgStatuses === undefined) {
index df91989c4a84fe64cdfa2ae33b1677e756cb9001..64993e86a8ff575d7a1f46bb6c7f13f389f1179f 100644 (file)
@@ -64,7 +64,9 @@ export function QualityGatePanelSection(props: QualityGatePanelSectionProps) {
               isNewCode={isNewCode}
               isApplication={isApplication}
               qualityGate={qualityGate}
-              qgStatus={qgStatus}
+              failedConditions={qgStatus.failedConditions}
+              branchLike={qgStatus.branchLike}
+              component={qgStatus}
             />
           </BorderlessAccordion>
 
@@ -75,7 +77,9 @@ export function QualityGatePanelSection(props: QualityGatePanelSectionProps) {
           isNewCode={isNewCode}
           isApplication={isApplication}
           qualityGate={qualityGate}
-          qgStatus={qgStatus}
+          failedConditions={qgStatus.failedConditions}
+          branchLike={qgStatus.branchLike}
+          component={qgStatus}
         />
       )}
     </>
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCard.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCard.tsx
deleted file mode 100644 (file)
index 7f77a7d..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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 styled from '@emotion/styled';
-import {
-  HelperHintIcon,
-  LightGreyCard,
-  LightLabel,
-  SnoozeCircleIcon,
-  TextError,
-  TextSubdued,
-  TrendDownCircleIcon,
-  TrendUpCircleIcon,
-  themeColor,
-} from 'design-system';
-import * as React from 'react';
-import { useIntl } from 'react-intl';
-import { getBranchLikeQuery } from '~sonar-aligned/helpers/branch-like';
-import { formatMeasure } from '~sonar-aligned/helpers/measures';
-import { getComponentIssuesUrl } from '~sonar-aligned/helpers/urls';
-import { MetricKey, MetricType } from '~sonar-aligned/types/metrics';
-import Tooltip from '../../../components/controls/Tooltip';
-import { getLeakValue } from '../../../components/measure/utils';
-import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils';
-import { findMeasure } from '../../../helpers/measures';
-import { PullRequest } from '../../../types/branch-like';
-import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
-import { Component, MeasureEnhanced } from '../../../types/types';
-import { IssueMeasuresCardInner } from '../components/IssueMeasuresCardInner';
-import { Status, getConditionRequiredLabel } from '../utils';
-
-interface Props {
-  component: Component;
-  conditions: QualityGateStatusConditionEnhanced[];
-  measures: MeasureEnhanced[];
-  pullRequest: PullRequest;
-}
-
-export default function IssueMeasuresCard(
-  props: React.PropsWithChildren<Props & React.HTMLAttributes<HTMLDivElement>>,
-) {
-  const { measures, conditions, component, pullRequest, ...rest } = props;
-
-  const intl = useIntl();
-
-  const issuesCount = getLeakValue(findMeasure(measures, MetricKey.new_violations));
-  const issuesCondition = conditions.find((c) => c.metric === MetricKey.new_violations);
-  const issuesConditionFailed = issuesCondition?.level === Status.ERROR;
-  const fixedCount = findMeasure(measures, MetricKey.pull_request_fixed_issues)?.value;
-  const acceptedCount = getLeakValue(findMeasure(measures, MetricKey.new_accepted_issues));
-
-  const issuesUrl = getComponentIssuesUrl(component.key, {
-    ...getBranchLikeQuery(pullRequest),
-    ...DEFAULT_ISSUES_QUERY,
-  });
-  const fixedUrl = getComponentIssuesUrl(component.key, {
-    fixedInPullRequest: pullRequest.key,
-  });
-  const acceptedUrl = getComponentIssuesUrl(component.key, {
-    ...getBranchLikeQuery(pullRequest),
-    ...DEFAULT_ISSUES_QUERY,
-    issueStatuses: 'ACCEPTED',
-  });
-
-  return (
-    <LightGreyCard className="sw-p-8 sw-rounded-2 sw-flex sw-text-base sw-gap-4" {...rest}>
-      <IssueMeasuresCardInner
-        className="sw-w-1/3"
-        header={intl.formatMessage({ id: 'overview.new_issues' })}
-        data-testid={`overview__measures-${MetricKey.new_violations}`}
-        data-guiding-id={issuesConditionFailed ? 'overviewZeroNewIssuesSimplification' : undefined}
-        metric={MetricKey.new_violations}
-        value={formatMeasure(issuesCount, MetricType.ShortInteger)}
-        url={issuesUrl}
-        failed={issuesConditionFailed}
-        icon={issuesConditionFailed && <TrendUpCircleIcon />}
-        footer={
-          issuesCondition &&
-          (issuesConditionFailed ? (
-            <TextError
-              className="sw-font-regular sw-body-xs sw-inline"
-              text={getConditionRequiredLabel(issuesCondition, intl, true)}
-            />
-          ) : (
-            <LightLabel className="sw-body-xs">
-              {getConditionRequiredLabel(issuesCondition, intl)}
-            </LightLabel>
-          ))
-        }
-      />
-      <StyledCardSeparator />
-      <IssueMeasuresCardInner
-        className="sw-w-1/3"
-        header={intl.formatMessage({ id: 'overview.accepted_issues' })}
-        data-testid={`overview__measures-${MetricKey.new_accepted_issues}`}
-        metric={MetricKey.new_accepted_issues}
-        value={formatMeasure(acceptedCount, MetricType.ShortInteger)}
-        disabled={component.needIssueSync}
-        url={acceptedUrl}
-        icon={
-          acceptedCount && (
-            <SnoozeCircleIcon
-              color={acceptedCount === '0' ? 'overviewCardDefaultIcon' : 'overviewCardWarningIcon'}
-            />
-          )
-        }
-        footer={
-          <TextSubdued className="sw-body-xs">
-            {intl.formatMessage({ id: 'overview.accepted_issues.help' })}
-          </TextSubdued>
-        }
-      />
-      <StyledCardSeparator />
-      <IssueMeasuresCardInner
-        className="sw-w-1/3"
-        header={
-          <>
-            {intl.formatMessage({ id: 'overview.pull_request.fixed_issues' })}
-            <Tooltip
-              content={
-                <div className="sw-flex sw-flex-col sw-gap-4">
-                  <span>
-                    {intl.formatMessage({ id: 'overview.pull_request.fixed_issues.disclaimer' })}
-                  </span>
-                  <span>
-                    {intl.formatMessage({
-                      id: 'overview.pull_request.fixed_issues.disclaimer.2',
-                    })}
-                  </span>
-                </div>
-              }
-              side="top"
-            >
-              <HelperHintIcon raised />
-            </Tooltip>
-          </>
-        }
-        data-testid={`overview__measures-${MetricKey.pull_request_fixed_issues}`}
-        metric={MetricKey.pull_request_fixed_issues}
-        value={formatMeasure(fixedCount, MetricType.ShortInteger)}
-        disabled={component.needIssueSync}
-        url={fixedUrl}
-        icon={fixedCount && fixedCount !== '0' && <TrendDownCircleIcon />}
-        footer={
-          <TextSubdued className="sw-body-xs">
-            {intl.formatMessage({ id: 'overview.pull_request.fixed_issues.help' })}
-          </TextSubdued>
-        }
-      />
-    </LightGreyCard>
-  );
-}
-
-const StyledCardSeparator = styled.div`
-  width: 1px;
-  background-color: ${themeColor('projectCardBorder')};
-`;
index fc313e846e2a2ed926d7117c856040a3a97534d6..14bb087b4e5ab34cc4d536b9f6e7de58e3b7fa41 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import classNames from 'classnames';
+import {
+  Card,
+  HelperHintIcon,
+  LightLabel,
+  SnoozeCircleIcon,
+  TextError,
+  TextSubdued,
+  TrendDownCircleIcon,
+  TrendUpCircleIcon,
+} from 'design-system/lib';
 import * as React from 'react';
-import { getComponentSecurityHotspotsUrl } from '~sonar-aligned/helpers/urls';
-import { MetricKey } from '~sonar-aligned/types/metrics';
+import { useIntl } from 'react-intl';
+import {
+  getComponentIssuesUrl,
+  getComponentSecurityHotspotsUrl,
+} from '~sonar-aligned/helpers/urls';
+import { MetricKey, MetricType } from '~sonar-aligned/types/metrics';
+import Tooltip from '../../../components/controls/Tooltip';
 import { getLeakValue } from '../../../components/measure/utils';
+import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils';
 import { findMeasure } from '../../../helpers/measures';
 import { getComponentDrilldownUrl } from '../../../helpers/urls';
+import { getBranchLikeQuery } from '../../../sonar-aligned/helpers/branch-like';
+import { formatMeasure } from '../../../sonar-aligned/helpers/measures';
 import { PullRequest } from '../../../types/branch-like';
 import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
 import { Component, MeasureEnhanced } from '../../../types/types';
+import {
+  GridContainer,
+  StyleMeasuresCard,
+  StyleMeasuresCardRightBorder,
+  StyledConditionsCard,
+} from '../branches/BranchSummaryStyles';
+import FailedConditions from '../branches/FailedConditions';
+import { IssueMeasuresCardInner } from '../components/IssueMeasuresCardInner';
 import MeasuresCardNumber from '../components/MeasuresCardNumber';
 import MeasuresCardPercent from '../components/MeasuresCardPercent';
-import { MeasurementType, getMeasurementMetricKey } from '../utils';
-import IssueMeasuresCard from './IssueMeasuresCard';
+import {
+  MeasurementType,
+  Status,
+  getConditionRequiredLabel,
+  getMeasurementMetricKey,
+} from '../utils';
 
 interface Props {
-  className?: string;
   component: Component;
   conditions: QualityGateStatusConditionEnhanced[];
   measures: MeasureEnhanced[];
@@ -41,23 +70,144 @@ interface Props {
 }
 
 export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>) {
-  const { pullRequest, component, measures, conditions, className } = props;
+  const { pullRequest, component, measures, conditions } = props;
 
   const newSecurityHotspots = getLeakValue(
     findMeasure(measures, MetricKey.new_security_hotspots),
   ) as string;
 
-  return (
-    <>
-      <IssueMeasuresCard
-        conditions={conditions}
-        measures={measures}
-        component={component}
-        pullRequest={pullRequest}
-      />
+  const intl = useIntl();
+
+  const issuesCount = getLeakValue(findMeasure(measures, MetricKey.new_violations));
+  const issuesCondition = conditions.find((c) => c.metric === MetricKey.new_violations);
+  const isIssuesConditionFailed = issuesCondition?.level === Status.ERROR;
+  const fixedCount = findMeasure(measures, MetricKey.pull_request_fixed_issues)?.value;
+  const acceptedCount = getLeakValue(findMeasure(measures, MetricKey.new_accepted_issues));
+
+  const issuesUrl = getComponentIssuesUrl(component.key, {
+    ...getBranchLikeQuery(pullRequest),
+    ...DEFAULT_ISSUES_QUERY,
+  });
+  const fixedUrl = getComponentIssuesUrl(component.key, {
+    fixedInPullRequest: pullRequest.key,
+  });
+  const acceptedUrl = getComponentIssuesUrl(component.key, {
+    ...getBranchLikeQuery(pullRequest),
+    ...DEFAULT_ISSUES_QUERY,
+    issueStatuses: 'ACCEPTED',
+  });
 
-      <div className={classNames('sw-w-full sw-flex sw-flex-row sw-gap-4 sw-mt-4', className)}>
-        <div className="sw-flex-1 sw-flex sw-flex-col sw-gap-4">
+  const totalFailedConditions = conditions.filter((condition) => condition.level === Status.ERROR);
+
+  return (
+    <Card>
+      <GridContainer
+        className={classNames('sw-relative sw-overflow-hidden sw-mt-8 js-summary', {
+          'sw-grid-cols-3': totalFailedConditions.length === 0,
+          'sw-grid-cols-4': totalFailedConditions.length > 0,
+        })}
+      >
+        {totalFailedConditions.length > 0 && (
+          <StyledConditionsCard className="sw-row-span-3">
+            <FailedConditions
+              branchLike={pullRequest}
+              failedConditions={totalFailedConditions}
+              isNewCode
+              component={component}
+            />
+          </StyledConditionsCard>
+        )}
+        <StyleMeasuresCard>
+          <IssueMeasuresCardInner
+            header={intl.formatMessage({ id: 'overview.new_issues' })}
+            data-testid={`overview__measures-${MetricKey.new_violations}`}
+            data-guiding-id={
+              isIssuesConditionFailed ? 'overviewZeroNewIssuesSimplification' : undefined
+            }
+            metric={MetricKey.new_violations}
+            value={formatMeasure(issuesCount, MetricType.ShortInteger)}
+            url={issuesUrl}
+            failed={isIssuesConditionFailed}
+            icon={isIssuesConditionFailed && <TrendUpCircleIcon />}
+            footer={
+              issuesCondition &&
+              (isIssuesConditionFailed ? (
+                <TextError
+                  className="sw-font-regular sw-body-xs sw-inline"
+                  text={getConditionRequiredLabel(issuesCondition, intl, true)}
+                />
+              ) : (
+                <LightLabel className="sw-body-xs">
+                  {getConditionRequiredLabel(issuesCondition, intl)}
+                </LightLabel>
+              ))
+            }
+          />
+        </StyleMeasuresCard>
+        <StyleMeasuresCard>
+          <IssueMeasuresCardInner
+            header={intl.formatMessage({ id: 'overview.accepted_issues' })}
+            data-testid={`overview__measures-${MetricKey.new_accepted_issues}`}
+            metric={MetricKey.new_accepted_issues}
+            value={formatMeasure(acceptedCount, MetricType.ShortInteger)}
+            disabled={component.needIssueSync}
+            url={acceptedUrl}
+            icon={
+              acceptedCount && (
+                <SnoozeCircleIcon
+                  color={
+                    acceptedCount === '0' ? 'overviewCardDefaultIcon' : 'overviewCardWarningIcon'
+                  }
+                />
+              )
+            }
+            footer={
+              <TextSubdued className="sw-body-xs">
+                {intl.formatMessage({ id: 'overview.accepted_issues.help' })}
+              </TextSubdued>
+            }
+          />
+        </StyleMeasuresCard>
+        <StyleMeasuresCard>
+          <IssueMeasuresCardInner
+            header={
+              <>
+                {intl.formatMessage({ id: 'overview.pull_request.fixed_issues' })}
+                <Tooltip
+                  content={
+                    <div className="sw-flex sw-flex-col sw-gap-4">
+                      <span>
+                        {intl.formatMessage({
+                          id: 'overview.pull_request.fixed_issues.disclaimer',
+                        })}
+                      </span>
+                      <span>
+                        {intl.formatMessage({
+                          id: 'overview.pull_request.fixed_issues.disclaimer.2',
+                        })}
+                      </span>
+                    </div>
+                  }
+                  side="top"
+                >
+                  <HelperHintIcon raised />
+                </Tooltip>
+              </>
+            }
+            data-testid={`overview__measures-${MetricKey.pull_request_fixed_issues}`}
+            metric={MetricKey.pull_request_fixed_issues}
+            value={formatMeasure(fixedCount, MetricType.ShortInteger)}
+            disabled={component.needIssueSync}
+            url={fixedUrl}
+            icon={fixedCount && fixedCount !== '0' && <TrendDownCircleIcon />}
+            footer={
+              <TextSubdued className="sw-body-xs">
+                {intl.formatMessage({ id: 'overview.pull_request.fixed_issues.help' })}
+              </TextSubdued>
+            }
+          />
+        </StyleMeasuresCard>
+        <StyleMeasuresCardRightBorder>
           <MeasuresCardPercent
             componentKey={component.key}
             branchLike={pullRequest}
@@ -77,23 +227,8 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>)
             showRequired
             useDiffMetric
           />
-
-          <MeasuresCardNumber
-            label={
-              newSecurityHotspots === '1'
-                ? 'issue.type.SECURITY_HOTSPOT'
-                : 'issue.type.SECURITY_HOTSPOT.plural'
-            }
-            url={getComponentSecurityHotspotsUrl(component.key, pullRequest)}
-            value={newSecurityHotspots}
-            metric={MetricKey.new_security_hotspots}
-            conditions={conditions}
-            conditionMetric={MetricKey.new_security_hotspots_reviewed}
-            showRequired
-          />
-        </div>
-
-        <div className="sw-flex-1 sw-flex sw-flex-col sw-gap-4">
+        </StyleMeasuresCardRightBorder>
+        <StyleMeasuresCardRightBorder>
           <MeasuresCardPercent
             componentKey={component.key}
             branchLike={pullRequest}
@@ -113,8 +248,23 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>)
             useDiffMetric
             showRequired
           />
+        </StyleMeasuresCardRightBorder>
+        <div>
+          <MeasuresCardNumber
+            label={
+              newSecurityHotspots === '1'
+                ? 'issue.type.SECURITY_HOTSPOT'
+                : 'issue.type.SECURITY_HOTSPOT.plural'
+            }
+            url={getComponentSecurityHotspotsUrl(component.key, pullRequest)}
+            value={newSecurityHotspots}
+            metric={MetricKey.new_security_hotspots}
+            conditions={conditions}
+            conditionMetric={MetricKey.new_security_hotspots_reviewed}
+            showRequired
+          />
         </div>
-      </div>
-    </>
+      </GridContainer>
+    </Card>
   );
 }
index dc1954991d06e11c203ff934bc838224772b0d24..e5778e1bd4897491b4ebc0ebd28596260204ca9a 100644 (file)
@@ -98,8 +98,6 @@ export default function PullRequestOverview(props: Readonly<Readonly<Props>>) {
           <PullRequestMetaTopBar pullRequest={pullRequest} measures={measures} />
           <BasicSeparator className="sw-my-4" />
 
-          <AnalysisStatus className="sw-mb-4" component={component} />
-
           {ignoredConditions && <IgnoredConditionWarning />}
 
           <div className="sw-flex sw-justify-between sw-items-start sw-my-6">
@@ -107,8 +105,9 @@ export default function PullRequestOverview(props: Readonly<Readonly<Props>>) {
             <LastAnalysisLabel analysisDate={pullRequest.analysisDate} />
           </div>
 
+          <AnalysisStatus className="sw-mb-4" component={component} />
+
           <MeasuresCardPanel
-            className="sw-flex-1"
             pullRequest={pullRequest}
             component={component}
             conditions={enhancedConditions}