]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19018 Updating CaYC boxes in projects pages to MIUI
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Mon, 24 Apr 2023 13:48:29 +0000 (15:48 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 25 Apr 2023 20:03:01 +0000 (20:03 +0000)
16 files changed:
server/sonar-web/design-system/src/components/QualityGateIndicator.tsx
server/sonar-web/design-system/src/components/Text.tsx
server/sonar-web/design-system/src/components/__tests__/QualityGateIndicator-test.tsx
server/sonar-web/src/main/js/app/components/GlobalContainer.tsx
server/sonar-web/src/main/js/app/styles/init/type.css
server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx
server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx
server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx
server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarningOverCompliant.tsx
server/sonar-web/src/main/js/apps/overview/branches/NoCodeWarning.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/branches/__tests__/BranchOverview-it.tsx
server/sonar-web/src/main/js/apps/overview/components/QualityGateCondition.tsx
server/sonar-web/src/main/js/apps/overview/components/SonarLintPromotion.tsx
server/sonar-web/src/main/js/components/measure/__tests__/utils-test.tsx

index 0f0abf6a01272cd99b68cbdf6ca90ee5da6e0998..810269c357aa141f8e1f797ed8f8244ded1d82b6 100644 (file)
@@ -37,7 +37,6 @@ interface Props {
   size?: keyof typeof SIZE;
   status: QGStatus;
   tooltipPlacement?: BasePlacement;
-  withTooltip?: boolean;
 }
 
 const RX_4 = 4;
@@ -49,7 +48,6 @@ export function QualityGateIndicator(props: Props) {
     size = 'md',
     status,
     tooltipPlacement = PopupPlacement.Right,
-    withTooltip,
     ariaLabel,
   } = props;
   const iconProps = {
@@ -59,7 +57,6 @@ export function QualityGateIndicator(props: Props) {
     size,
     tooltipPlacement,
     width: SIZE[size],
-    withTooltip,
   };
   let StatusComponent: React.ReactNode;
   switch (status) {
@@ -94,17 +91,9 @@ interface IconProps {
   size: keyof typeof SIZE;
   tooltipPlacement?: BasePlacement;
   width: string;
-  withTooltip?: boolean;
 }
 
-function QGNotComputed({
-  className,
-  rx,
-  size,
-  tooltipPlacement,
-  withTooltip,
-  ...sizeProps
-}: IconProps) {
+function QGNotComputed({ className, rx, size, tooltipPlacement, ...sizeProps }: IconProps) {
   const theme = useTheme();
   const contrastColor = themeContrast('qgIndicatorNotComputed')({ theme });
   return (
@@ -121,7 +110,7 @@ function QGNotComputed({
   );
 }
 
-function QGPassed({ className, rx, size, tooltipPlacement, withTooltip, ...sizeProps }: IconProps) {
+function QGPassed({ className, rx, size, tooltipPlacement, ...sizeProps }: IconProps) {
   const theme = useTheme();
   const contrastColor = themeContrast('qgIndicatorPassed')({ theme });
   return (
@@ -153,7 +142,7 @@ function QGPassed({ className, rx, size, tooltipPlacement, withTooltip, ...sizeP
   );
 }
 
-function QGFailed({ className, rx, size, tooltipPlacement, withTooltip, ...sizeProps }: IconProps) {
+function QGFailed({ className, rx, size, tooltipPlacement, ...sizeProps }: IconProps) {
   const theme = useTheme();
   const contrastColor = themeContrast('qgIndicatorFailed')({ theme });
   return (
index 775091713c542c2f991bddce2d15e595008291c6..14da5264f36ec83dc79c26753eb07d2d82c73f84 100644 (file)
@@ -101,3 +101,7 @@ export const LightLabel = styled.span`
 export const LightPrimary = styled.span`
   color: ${themeContrast('primaryLight')};
 `;
+
+export const PageContentFontWrapper = styled.div`
+  color: ${themeColor('pageContent')};
+`;
index 20c0ef8bc2f7201e851648a1f1dbefaa8bc2098e..4dfa80ac5af4f5b8b12c40b8659452822b35a1d2 100644 (file)
@@ -50,15 +50,14 @@ it.each([
 it('should display tooltip', () => {
   const { rerender } = setupWithProps({
     status: 'NONE',
-    withTooltip: true,
     ariaLabel: 'label-none',
   });
   expect(screen.getByLabelText('label-none')).toBeInTheDocument();
 
-  rerender(<QualityGateIndicator ariaLabel="label-ok" status="OK" withTooltip={true} />);
+  rerender(<QualityGateIndicator ariaLabel="label-ok" status="OK" />);
   expect(screen.getByLabelText('label-ok')).toBeInTheDocument();
 
-  rerender(<QualityGateIndicator ariaLabel="label-error" status="ERROR" withTooltip={true} />);
+  rerender(<QualityGateIndicator ariaLabel="label-error" status="ERROR" />);
   expect(screen.getByLabelText('label-error')).toBeInTheDocument();
 });
 
index ce3f0c22d950e03019c8656a870d8f32555cbe31..e9bf7fb47617d7e22a8dd013210ed71c9d52f1b4 100644 (file)
@@ -18,6 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import { ThemeProvider } from '@emotion/react';
+import classNames from 'classnames';
 import { lightTheme } from 'design-system';
 import * as React from 'react';
 import { Outlet, useLocation } from 'react-router-dom';
@@ -25,18 +26,20 @@ import A11yProvider from '../../components/a11y/A11yProvider';
 import A11ySkipLinks from '../../components/a11y/A11ySkipLinks';
 import SuggestionsProvider from '../../components/embed-docs-modal/SuggestionsProvider';
 import Workspace from '../../components/workspace/Workspace';
-import BranchStatusContextProvider from './branch-status/BranchStatusContextProvider';
 import GlobalFooter from './GlobalFooter';
+import StartupModal from './StartupModal';
+import SystemAnnouncement from './SystemAnnouncement';
+import BranchStatusContextProvider from './branch-status/BranchStatusContextProvider';
 import IndexationContextProvider from './indexation/IndexationContextProvider';
 import IndexationNotification from './indexation/IndexationNotification';
 import LanguagesContextProvider from './languages/LanguagesContextProvider';
 import MetricsContextProvider from './metrics/MetricsContextProvider';
 import GlobalNav from './nav/global/GlobalNav';
 import PromotionNotification from './promotion-notification/PromotionNotification';
-import StartupModal from './StartupModal';
-import SystemAnnouncement from './SystemAnnouncement';
 import UpdateNotification from './update-notification/UpdateNotification';
 
+const TEMP_PAGELIST_WITH_NEW_BACKGROUND = ['/dashboard'];
+
 export default function GlobalContainer() {
   // it is important to pass `location` down to `GlobalNav` to trigger render on url change
   const location = useLocation();
@@ -48,7 +51,12 @@ export default function GlobalContainer() {
           <StartupModal>
             <A11ySkipLinks />
             <div className="global-container">
-              <div className="page-wrapper" id="container">
+              <div
+                className={classNames('page-wrapper', {
+                  'new-background': TEMP_PAGELIST_WITH_NEW_BACKGROUND.includes(location.pathname),
+                })}
+                id="container"
+              >
                 <div className="page-container">
                   <BranchStatusContextProvider>
                     <Workspace>
index 874e032e73dcc76a59444137cb9dc95c4d56d832..03f5f3b27ea2b8024429a65ea2f27af52f40a224 100644 (file)
@@ -302,3 +302,7 @@ small,
   font-family: var(--sourceCodeFontFamily);
   font-size: var(--smallFontSize);
 }
+
+.new-background {
+  background-color: #fcfcfd;
+}
index e1fc30b255b4434432fd794cc4f51bb95a91f2bc..e8f6fc3c1bccd501255b35f43059922df0d7db28 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 { Card, FlagMessage, Link } from 'design-system';
 import * as React from 'react';
-import DocLink from '../../../components/common/DocLink';
-import Link from '../../../components/common/Link';
-import QualifierIcon from '../../../components/icons/QualifierIcon';
-import { Alert } from '../../../components/ui/Alert';
+import withAppStateContext, {
+  WithAppStateContextProps,
+} from '../../../app/components/app-state/withAppStateContext';
 import { getBranchLikeQuery } from '../../../helpers/branch-like';
+import { getUrlForDoc } from '../../../helpers/docs';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { getProjectQueryUrl } from '../../../helpers/urls';
-import { ComponentQualifier } from '../../../types/component';
 import { QualityGateStatus } from '../../../types/quality-gates';
 import { CaycStatus } from '../../../types/types';
 
@@ -34,18 +34,34 @@ interface Props {
   caycStatus: CaycStatus;
 }
 
-export default function ApplicationNonCaycProjectWarning({ projects, caycStatus }: Props) {
+function ApplicationNonCaycProjectWarning({
+  projects,
+  caycStatus,
+  appState,
+}: Props & WithAppStateContextProps) {
+  const caycUrl = getUrlForDoc(appState.version, '/user-guide/clean-as-you-code/');
+  const caycDrawbacksUrl = getUrlForDoc(
+    appState.version,
+    '/user-guide/clean-as-you-code/#potential-drawbacks'
+  );
+
   return (
-    <div className="overview-quality-gate-conditions-list padded big-spacer-top">
+    <Card className="sw-mt-4 sw-body-sm">
       {caycStatus === CaycStatus.NonCompliant ? (
-        <Alert variant="warning">
+        <FlagMessage
+          ariaLabel={translateWithParameters(
+            'overview.quality_gate.application.non_cayc.projects_x',
+            projects.length
+          )}
+          variant="warning"
+        >
           {translateWithParameters(
             'overview.quality_gate.application.non_cayc.projects_x',
             projects.length
           )}
-        </Alert>
+        </FlagMessage>
       ) : (
-        <p className="padded">
+        <p className="sw-p-2">
           {translateWithParameters(
             'overview.quality_gate.application.cayc_over_compliant.projects_x',
             projects.length
@@ -53,34 +69,25 @@ export default function ApplicationNonCaycProjectWarning({ projects, caycStatus
         </p>
       )}
 
-      <ul className="spacer-left spacer-bottom big-spacer-top">
+      <ul className="sw-mt-4 sw-ml-2 sw-mb-2">
         {projects.map(({ key, name, branchLike }) => (
-          <li key={key} className="text-ellipsis spacer-bottom" title={name}>
-            <Link
-              className="link-no-underline"
-              to={getProjectQueryUrl(key, getBranchLikeQuery(branchLike))}
-            >
-              <QualifierIcon
-                className="little-spacer-right"
-                qualifier={ComponentQualifier.Project}
-              />
-              {name}
-            </Link>
+          <li key={key} className="sw-text-ellipsis sw-mb-2" title={name}>
+            <Link to={getProjectQueryUrl(key, getBranchLikeQuery(branchLike))}>{name}</Link>
           </li>
         ))}
       </ul>
-      <hr className="big-spacer-top big-spacer-bottom" />
-      <div className="spacer spacer-bottom big-spacer-top">
+      <hr className="sw-my-4" />
+      <div className="sw-m-2 sw-mt-4">
         {caycStatus === CaycStatus.NonCompliant ? (
-          <DocLink to="/user-guide/clean-as-you-code/">
-            {translate('overview.quality_gate.conditions.cayc.link')}
-          </DocLink>
+          <Link to={caycUrl}>{translate('overview.quality_gate.conditions.cayc.link')}</Link>
         ) : (
-          <DocLink to="/user-guide/clean-as-you-code/#potential-drawbacks">
+          <Link to={caycDrawbacksUrl}>
             {translate('overview.quality_gate.conditions.cayc_over_compliant.link')}
-          </DocLink>
+          </Link>
         )}
       </div>
-    </div>
+    </Card>
   );
 }
+
+export default withAppStateContext(ApplicationNonCaycProjectWarning);
index 7593b4ae651fe3a847d928b96fc451b59b96b26a..ddcb860be48746c8e14ff9e6e7600736bd9819e0 100644 (file)
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { LargeCenteredLayout } from 'design-system';
+import { LargeCenteredLayout, PageContentFontWrapper } from 'design-system';
 import * as React from 'react';
 import A11ySkipTarget from '../../../components/a11y/A11ySkipTarget';
 import { parseDate } from '../../../helpers/dates';
@@ -86,49 +86,51 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp
         projectBinding={projectBinding}
       />
       <LargeCenteredLayout>
-        <div className="overview sw-mt-6">
-          <A11ySkipTarget anchor="overview_main" />
+        <PageContentFontWrapper>
+          <div className="overview sw-mt-6 sw-body-sm">
+            <A11ySkipTarget anchor="overview_main" />
 
-          {projectIsEmpty ? (
-            <NoCodeWarning branchLike={branch} component={component} measures={measures} />
-          ) : (
-            <div className="sw-flex">
-              <div className="width-30 sw-mr-12 sw-pt-6">
-                <QualityGatePanel
-                  component={component}
-                  loading={loadingStatus}
-                  qgStatuses={qgStatuses}
-                />
-              </div>
-
-              <div className="sw-flex-1">
-                <div className="sw-flex sw-flex-col sw-pt-6">
-                  <MeasuresPanel
-                    appLeak={appLeak}
-                    branch={branch}
+            {projectIsEmpty ? (
+              <NoCodeWarning branchLike={branch} component={component} measures={measures} />
+            ) : (
+              <div className="sw-flex">
+                <div className="sw-w-1/3 sw-mr-12 sw-pt-6">
+                  <QualityGatePanel
                     component={component}
                     loading={loadingStatus}
-                    measures={measures}
-                    period={period}
                     qgStatuses={qgStatuses}
                   />
+                </div>
 
-                  <ActivityPanel
-                    analyses={analyses}
-                    branchLike={branch}
-                    component={component}
-                    graph={graph}
-                    leakPeriodDate={leakPeriod && parseDate(leakPeriod.date)}
-                    loading={loadingHistory}
-                    measuresHistory={measuresHistory}
-                    metrics={metrics}
-                    onGraphChange={onGraphChange}
-                  />
+                <div className="sw-flex-1">
+                  <div className="sw-flex sw-flex-col sw-pt-6">
+                    <MeasuresPanel
+                      appLeak={appLeak}
+                      branch={branch}
+                      component={component}
+                      loading={loadingStatus}
+                      measures={measures}
+                      period={period}
+                      qgStatuses={qgStatuses}
+                    />
+
+                    <ActivityPanel
+                      analyses={analyses}
+                      branchLike={branch}
+                      component={component}
+                      graph={graph}
+                      leakPeriodDate={leakPeriod && parseDate(leakPeriod.date)}
+                      loading={loadingHistory}
+                      measuresHistory={measuresHistory}
+                      metrics={metrics}
+                      onGraphChange={onGraphChange}
+                    />
+                  </div>
                 </div>
               </div>
-            </div>
-          )}
-        </div>
+            )}
+          </div>
+        </PageContentFontWrapper>
       </LargeCenteredLayout>
     </>
   );
index 19a876a7889f299f2eace2c6e7a58277c7a8f542..746f5fa5a7fa94b4e17d76d925264fe834c2ff71 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 { DiscreetLink, FlagMessage, Link } from 'design-system';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
-import DocLink from '../../../components/common/DocLink';
-import Link from '../../../components/common/Link';
-import { Alert } from '../../../components/ui/Alert';
+import withAppStateContext, {
+  WithAppStateContextProps,
+} from '../../../app/components/app-state/withAppStateContext';
+import { getUrlForDoc } from '../../../helpers/docs';
 import { translate } from '../../../helpers/l10n';
 import { getQualityGateUrl } from '../../../helpers/urls';
 import { Component } from '../../../types/types';
@@ -30,33 +32,38 @@ interface Props {
   component: Pick<Component, 'key' | 'qualifier' | 'qualityGate'>;
 }
 
-export default function CleanAsYouCodeWarning({ component }: Props) {
+function CleanAsYouCodeWarning({ component, appState }: Props & WithAppStateContextProps) {
+  const caycUrl = getUrlForDoc(appState.version, '/user-guide/clean-as-you-code/');
+
   return (
     <>
-      <Alert variant="warning">{translate('overview.quality_gate.conditions.cayc.warning')}</Alert>
+      <FlagMessage
+        ariaLabel={translate('overview.quality_gate.conditions.cayc.warning')}
+        variant="warning"
+      >
+        {translate('overview.quality_gate.conditions.cayc.warning')}
+      </FlagMessage>
       {component.qualityGate ? (
-        <p className="big-spacer-top big-spacer-bottom">
+        <p className="sw-my-4">
           <FormattedMessage
             id="overview.quality_gate.conditions.cayc.details_with_link"
             defaultMessage={translate('overview.quality_gate.conditions.cayc.details_with_link')}
             values={{
               link: (
-                <Link to={getQualityGateUrl(component.qualityGate.name)}>
+                <DiscreetLink to={getQualityGateUrl(component.qualityGate.name)}>
                   {translate('overview.quality_gate.conditions.non_cayc.warning.link')}
-                </Link>
+                </DiscreetLink>
               ),
             }}
           />
         </p>
       ) : (
-        <p className="big-spacer-top big-spacer-bottom">
-          {translate('overview.quality_gate.conditions.cayc.details')}
-        </p>
+        <p className="sw-my-4">{translate('overview.quality_gate.conditions.cayc.details')}</p>
       )}
 
-      <DocLink to="/user-guide/clean-as-you-code/">
-        {translate('overview.quality_gate.conditions.cayc.link')}
-      </DocLink>
+      <Link to={caycUrl}>{translate('overview.quality_gate.conditions.cayc.link')}</Link>
     </>
   );
 }
+
+export default withAppStateContext(CleanAsYouCodeWarning);
index f055badf67cd5ea97a7d6289f6755aba25e40144..c2a5e08982ef18fda031601f280ded3d78edab36 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 { DiscreetLink, Link } from 'design-system';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
-import DocLink from '../../../components/common/DocLink';
-import Link from '../../../components/common/Link';
+import withAppStateContext, {
+  WithAppStateContextProps,
+} from '../../../app/components/app-state/withAppStateContext';
+import { getUrlForDoc } from '../../../helpers/docs';
 import { translate } from '../../../helpers/l10n';
 import { getQualityGateUrl } from '../../../helpers/urls';
 import { Component } from '../../../types/types';
@@ -29,11 +32,19 @@ interface Props {
   component: Pick<Component, 'key' | 'qualifier' | 'qualityGate'>;
 }
 
-export default function CleanAsYouCodeWarningOverCompliant({ component }: Props) {
+function CleanAsYouCodeWarningOverCompliant({
+  component,
+  appState,
+}: Props & WithAppStateContextProps) {
+  const caycDrawbackUrl = getUrlForDoc(
+    appState.version,
+    '/user-guide/clean-as-you-code/#potential-drawbacks'
+  );
+
   return (
     <>
       {component.qualityGate ? (
-        <p className="big-spacer-bottom">
+        <p className="sw-mb-4">
           <FormattedMessage
             id="overview.quality_gate.conditions.cayc_over_compliant.details_with_link"
             defaultMessage={translate(
@@ -41,22 +52,24 @@ export default function CleanAsYouCodeWarningOverCompliant({ component }: Props)
             )}
             values={{
               link: (
-                <Link to={getQualityGateUrl(component.qualityGate.name)}>
+                <DiscreetLink to={getQualityGateUrl(component.qualityGate.name)}>
                   {translate('overview.quality_gate.conditions.cayc_over_compliant.warning.link')}
-                </Link>
+                </DiscreetLink>
               ),
             }}
           />
         </p>
       ) : (
-        <p className="big-spacer-bottom">
+        <p className="sw-mb-4">
           {translate('overview.quality_gate.conditions.cayc_over_compliant.details')}
         </p>
       )}
 
-      <DocLink to="/user-guide/clean-as-you-code/#potential-drawbacks">
+      <Link to={caycDrawbackUrl}>
         {translate('overview.quality_gate.conditions.cayc_over_compliant.link')}
-      </DocLink>
+      </Link>
     </>
   );
 }
+
+export default withAppStateContext(CleanAsYouCodeWarningOverCompliant);
index 8810fbb8e064542ff76f746b222b3580e9b75eca..19a939a74c4b3e2380150f38c98b0208d674d348 100644 (file)
@@ -17,8 +17,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { FlagMessage } from 'design-system';
 import * as React from 'react';
-import { Alert } from '../../../components/ui/Alert';
 import { getBranchLikeDisplayName, isMainBranch } from '../../../helpers/branch-like';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { BranchLike } from '../../../types/branch-like';
@@ -84,9 +84,9 @@ export function NoCodeWarning({ branchLike, component, measures }: Props) {
   /* eslint-enable no-lonely-if */
 
   return (
-    <Alert display="banner" variant="warning">
+    <FlagMessage ariaLabel={title} variant="warning">
       {title}
-    </Alert>
+    </FlagMessage>
   );
 }
 
index 063142c02b58d4808ade8c4af0b0819ace6ddeb4..bdea28e3c36b06c56652b847432d03730511c5fa 100644 (file)
@@ -29,6 +29,8 @@ import QualityGateStatusPassedView from '../components/QualityGateStatusPassedVi
 import { QualityGateStatusTitle } from '../components/QualityGateStatusTitle';
 import SonarLintPromotion from '../components/SonarLintPromotion';
 import ApplicationNonCaycProjectWarning from './ApplicationNonCaycProjectWarning';
+import CleanAsYouCodeWarning from './CleanAsYouCodeWarning';
+import CleanAsYouCodeWarningOverCompliant from './CleanAsYouCodeWarningOverCompliant';
 import QualityGatePanelSection from './QualityGatePanelSection';
 
 export interface QualityGatePanelProps {
@@ -119,6 +121,23 @@ export function QualityGatePanel(props: QualityGatePanelProps) {
           caycStatus={CaycStatus.OverCompliant}
         />
       )}
+
+      {qgStatuses.length === 1 &&
+        qgStatuses[0].caycStatus === CaycStatus.NonCompliant &&
+        !isApplication(component.qualifier) && (
+          <Card className="sw-mt-4 sw-body-sm">
+            <CleanAsYouCodeWarning component={component} />
+          </Card>
+        )}
+
+      {qgStatuses.length === 1 &&
+        qgStatuses[0].caycStatus === CaycStatus.OverCompliant &&
+        !isApplication(component.qualifier) && (
+          <Card className="sw-mt-4 sw-body-sm">
+            <CleanAsYouCodeWarningOverCompliant component={component} />
+          </Card>
+        )}
+
       <SonarLintPromotion
         qgConditions={flatMap(qgStatuses, (qgStatus) => qgStatus.failedConditions)}
       />
index d4ceaf05679df5417120a18cd57586d2ed0be36a..e557ea0f5260c3db39ce21292c397f2ed290c8df 100644 (file)
@@ -29,8 +29,6 @@ import {
 } from '../../../types/quality-gates';
 import { CaycStatus, Component } from '../../../types/types';
 import QualityGateConditions from '../components/QualityGateConditions';
-import CleanAsYouCodeWarning from './CleanAsYouCodeWarning';
-import CleanAsYouCodeWarningOverCompliant from './CleanAsYouCodeWarningOverCompliant';
 
 export interface QualityGatePanelSectionProps {
   branchLike?: BranchLike;
@@ -176,21 +174,7 @@ export function QualityGatePanelSection(props: QualityGatePanelSectionProps) {
           <BasicSeparator />
         </>
       ) : (
-        <>
-          {renderFailedConditions()}
-          {qgStatus.caycStatus === CaycStatus.NonCompliant &&
-            !isApplication(component.qualifier) && (
-              <div className="big-padded bordered-bottom overview-quality-gate-conditions-list">
-                <CleanAsYouCodeWarning component={component} />
-              </div>
-            )}
-          {qgStatus.caycStatus === CaycStatus.OverCompliant &&
-            !isApplication(component.qualifier) && (
-              <div className="big-padded bordered-bottom overview-quality-gate-conditions-list">
-                <CleanAsYouCodeWarningOverCompliant component={component} />
-              </div>
-            )}
-        </>
+        renderFailedConditions()
       )}
     </>
   );
index 93f8b78d68731e1d55da549f8c498ef0fa71f00d..203aeb5a512ac2ae5e93b014c61b1452efbc1f63 100644 (file)
@@ -232,6 +232,21 @@ describe('project overview', () => {
     expect(screen.getByText('overview.quality_gate.conditions.cayc.warning')).toBeInTheDocument();
   });
 
+  it('should show Cayc message when QG is over-compliant', async () => {
+    jest
+      .mocked(getQualityGateProjectStatus)
+      .mockResolvedValueOnce(
+        mockQualityGateProjectStatus({ status: 'OK', caycStatus: CaycStatus.OverCompliant })
+      );
+
+    renderBranchOverview();
+
+    expect(await screen.findByText('metric.level.OK')).toBeInTheDocument();
+    expect(
+      screen.getByText('overview.quality_gate.conditions.cayc_over_compliant.link')
+    ).toBeInTheDocument();
+  });
+
   it('should show a failed QG', async () => {
     renderBranchOverview();
 
index 73476f95598072da2b305cf27a060aa0bfc06a3e..78409d0e74e742bfc644f39777bec8cc59bb4be0 100644 (file)
@@ -111,21 +111,17 @@ export default class QualityGateCondition extends React.PureComponent<Props> {
       return <LinkBox to={METRICS_TO_URL_MAPPING[metricKey]()}>{children}</LinkBox>;
     }
 
-    if (isIssueMeasure(condition.measure.metric.key)) {
-      const url = getComponentIssuesUrl(component.key, {
-        ...propsToIssueParams(condition.measure.metric.key, condition.period != null),
-        ...getBranchLikeQuery(branchLike),
-      });
-
-      return <LinkBox to={url}>{children}</LinkBox>;
-    }
-
-    const url = getComponentDrilldownUrl({
-      componentKey: component.key,
-      metric: condition.measure.metric.key,
-      branchLike,
-      listView: true,
-    });
+    const url = isIssueMeasure(condition.measure.metric.key)
+      ? getComponentIssuesUrl(component.key, {
+          ...propsToIssueParams(condition.measure.metric.key, condition.period != null),
+          ...getBranchLikeQuery(branchLike),
+        })
+      : getComponentDrilldownUrl({
+          componentKey: component.key,
+          metric: condition.measure.metric.key,
+          branchLike,
+          listView: true,
+        });
 
     return <LinkBox to={url}>{children}</LinkBox>;
   }
index 67a41dc2c348cd16701bc435644b22d8a31bad70..625dc9c628248bc393afee6e8a1d9de5597804b7 100644 (file)
@@ -68,10 +68,13 @@ export function SonarLintPromotion({ currentUser, qgConditions }: SonarLintPromo
                 rel="noopener noreferrer"
                 target="_blank"
                 showExternalIcon={false}
+                className="sw-mr-1"
               >
                 SonarLint
               </DiscreetLink>
-              <SonarLintIcon size={16} />
+              <span className="sw-align-middle">
+                <SonarLintIcon size={16} />
+              </span>
             </>
           ),
         }}
index 0428864b305897c18bb694f7081c54426bbeeb6f..83084356feccbd2acf1c937cbd05531423f21013 100644 (file)
 import { duplicationRatingConverter } from '../utils';
 
 describe('duplicationRatingConverter', () => {
-  it('should work correctly for different use cases', () => {
-    expect(duplicationRatingConverter(-10)).toEqual('A');
-    expect(duplicationRatingConverter(2)).toEqual('A');
-    expect(duplicationRatingConverter(4)).toEqual('B');
-    expect(duplicationRatingConverter(8)).toEqual('C');
-    expect(duplicationRatingConverter(18)).toEqual('D');
-    expect(duplicationRatingConverter(20)).toEqual('E');
-    expect(duplicationRatingConverter(25)).toEqual('E');
+  it.each([
+    [-10, 'A'],
+    [2, 'A'],
+    [4, 'B'],
+    [8, 'C'],
+    [18, 'D'],
+    [20, 'E'],
+    [25, 'E'],
+  ])('should work correctly when value is %s', (value: number, result: string) => {
+    expect(duplicationRatingConverter(value)).toEqual(result);
   });
 });