From 5f5d2fa963722569f6e44e5cead762cd4de28ab4 Mon Sep 17 00:00:00 2001 From: 7PH Date: Thu, 25 Jan 2024 15:13:28 +0100 Subject: [PATCH] SONAR-21455 Implement a no-data state for missing software quality measures --- .../design-system/src/components/Card.tsx | 4 - .../branches/BranchOverallCodePanel.tsx | 2 +- .../branches/BranchOverviewRenderer.tsx | 62 +++++++---- .../SoftwareImpactMeasureBreakdownCard.tsx | 72 ++++++------ .../branches/SoftwareImpactMeasureCard.tsx | 103 ++++++++++++------ .../resources/org/sonar/l10n/core.properties | 4 + 6 files changed, 153 insertions(+), 94 deletions(-) diff --git a/server/sonar-web/design-system/src/components/Card.tsx b/server/sonar-web/design-system/src/components/Card.tsx index 3093905fa9f..cd0a80dd9cb 100644 --- a/server/sonar-web/design-system/src/components/Card.tsx +++ b/server/sonar-web/design-system/src/components/Card.tsx @@ -63,7 +63,3 @@ const LightGreyCardStyled = styled(CardStyled)` const GreyCardStyled = styled(CardStyled)` border: ${themeBorder('default', 'almCardBorder')}; `; - -const LightGreyCardStyled = styled(CardStyled)` - border: ${themeBorder('default')}; -`; diff --git a/server/sonar-web/src/main/js/apps/overview/branches/BranchOverallCodePanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/BranchOverallCodePanel.tsx index e483b2dd44f..3f9e7d9d7f0 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/BranchOverallCodePanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/BranchOverallCodePanel.tsx @@ -32,7 +32,7 @@ export default function BranchOverallCodePanel(props: Readonly +
{ return query.codeScope === CodeScope.Overall ? MeasuresTabs.Overall : MeasuresTabs.New; }); + const intl = useIntl(); + + // Check if any potentially missing uncomputed measure is not present + const isMissingMeasures = [ + MetricKey.new_accepted_issues, + MetricKey.security_issues, + MetricKey.maintainability_issues, + MetricKey.reliability_issues, + ].some((key) => !measures.find((measure) => measure.metric.key === key)); const leakPeriod = component.qualifier === ComponentQualifier.Application ? appLeak : period; const isNewCodeTab = tab === MeasuresTabs.New; @@ -169,6 +181,20 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp /> )} + {hasNewCodeMeasures && + isMissingMeasures && + isApplication(component.qualifier) && ( + + {intl.formatMessage({ + id: 'overview.missing_project_data.APP', + })} + + )} + + {!isNewCodeTab && ( + + )} + {hasNewCodeMeasures && isNewCodeTab && ( )} - {!isNewCodeTab && ( - <> - {!isNewCodeTab && ( - - )} - - + - - - )} + -; + } + return ( - - {formatMeasure(value, MetricType.ShortInteger)} - - {intl.formatMessage({ - id: `overview.measures.software_impact.severity.${severity}`, - })} - + + + {formatMeasure(value, MetricType.ShortInteger)} + + {intl.formatMessage({ + id: `overview.measures.software_impact.severity.${severity}`, + })} + + ); } -const StyledBreakdownCard = styled(DiscreetLinkBox)` +const StyledBreakdownCard = styled.div` background-color: ${themeColor('overviewSoftwareImpactSeverityNeutral')}; &.active.HIGH { diff --git a/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx b/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx index e9a19944674..4dc51df7ced 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx @@ -17,7 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { BasicSeparator, LightGreyCard, NakedLink, TextBold, TextSubdued } from 'design-system'; +import styled from '@emotion/styled'; +import classNames from 'classnames'; +import { + BasicSeparator, + LightGreyCard, + NakedLink, + TextBold, + TextSubdued, + themeColor, +} from 'design-system'; import * as React from 'react'; import { useIntl } from 'react-intl'; import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils'; @@ -51,11 +60,6 @@ export function SoftwareImpactMeasureCard(props: Readonly m.metric.key === metricKey); const measure = JSON.parse(measureRaw?.value ?? 'null') as SoftwareImpactMeasureData | null; - // Hide this card if there is no measure - if (!measure) { - return null; - } - // Find rating measure const ratingMeasure = measures.find((m) => m.metric.key === ratingMetricKey); const ratingLabel = ratingMeasure?.value ? formatRating(ratingMeasure.value) : undefined; @@ -66,39 +70,47 @@ export function SoftwareImpactMeasureCard(props: Readonly issuesCount > 0)?.[0] - : null; + let highlightedSeverity: SoftwareImpactSeverity | undefined; + if (measure && (!ratingLabel || ratingLabel !== 'A')) { + const issuesBySeverity: [SoftwareImpactSeverity, number][] = [ + [SoftwareImpactSeverity.High, measure.high], + [SoftwareImpactSeverity.Medium, measure.medium], + [SoftwareImpactSeverity.Low, measure.low], + ]; + highlightedSeverity = issuesBySeverity.find(([_, issuesCount]) => issuesCount > 0)?.[0]; + } return ( - +
-
- - {formatMeasure(measure.total, MetricType.ShortInteger)} - +
+ {measure ? ( + + {formatMeasure(measure.total, MetricType.ShortInteger)} + + ) : ( + + )} {intl.formatMessage({ id: 'overview.measures.software_impact.total_open_issues' })} @@ -119,15 +131,36 @@ export function SoftwareImpactMeasureCard(props: Readonly ))}
+ {!measure && ( + <> + + + {intl.formatMessage({ id: 'overview.project.no_data' })} + + {intl.formatMessage({ + id: `overview.run_analysis_to_compute.${component.qualifier}`, + })} + + + + )} ); } +const StyledDash = styled(TextBold)` + font-size: 36px; +`; + +const StyledInfoSection = styled.div` + background-color: ${themeColor('overviewSoftwareImpactSeverityNeutral')}; +`; + export default SoftwareImpactMeasureCard; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 1548fd4e461..230e8e85d38 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3960,6 +3960,10 @@ overview.project.next_steps.set_up_pr_deco=To benefit from more of SonarQube's f overview.project.next_steps.set_up_ci=To benefit from more of SonarQube's features, {link}. overview.project.next_steps.links.project_settings=project settings overview.project.next_steps.links.set_up_ci=set up analysis in your favorite CI +overview.project.no_data=No data. +overview.run_analysis_to_compute.TRK=Run new analysis to compute. +overview.run_analysis_to_compute.APP=All projects need to be analysed. +overview.missing_project_data.APP=Some projects are missing data. All projects in the application need to be analysed. overview.coverage_on=Coverage on overview.coverage_on_X_lines=Coverage on {count} Lines to cover -- 2.39.5