From b9b7c04a09d20c8b99a60d10d19d4174fc15b2f9 Mon Sep 17 00:00:00 2001 From: Ambroise C Date: Mon, 16 Oct 2023 16:20:09 +0200 Subject: [PATCH] SONAR-20673 Improve the way we display the quality gate status for each analysis --- .../apps/overview/branches/ActivityPanel.tsx | 11 +++++++ .../js/apps/overview/branches/Analysis.tsx | 33 ++++++++++++++++--- .../branches/__tests__/ActivityPanel-it.tsx | 12 ++++++- .../src/main/js/apps/overview/utils.ts | 1 + 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx index a5f6c732e78..67ed4414dc1 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx @@ -32,6 +32,7 @@ import { parseDate } from '../../../helpers/dates'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { localizeMetric } from '../../../helpers/measures'; import { BranchLike } from '../../../types/branch-like'; +import { MetricKey } from '../../../types/metrics'; import { Analysis as AnalysisType, GraphType, @@ -100,6 +101,15 @@ export function ActivityPanel(props: ActivityPanelProps) { [measuresHistory, analyses.length], ); + const qualityGateStatuses = React.useMemo( + () => + measuresHistory + .find(({ metric }) => metric === MetricKey.alert_status) + ?.history.slice(-MAX_ANALYSES_NB) + .reverse(), + [measuresHistory], + ); + return (
@@ -135,6 +145,7 @@ export function ActivityPanel(props: ActivityPanelProps) { analysis={analysis} isFirstAnalysis={index === analyses.length - 1} qualifier={component.qualifier} + qualityGateStatus={qualityGateStatuses?.[index]?.value} variations={analysisVariations[index]} /> {index !== displayedAnalyses.length - 1 && } diff --git a/server/sonar-web/src/main/js/apps/overview/branches/Analysis.tsx b/server/sonar-web/src/main/js/apps/overview/branches/Analysis.tsx index 88507be61db..c46c684f2f4 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/Analysis.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/Analysis.tsx @@ -17,8 +17,10 @@ * 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 { sortBy } from 'lodash'; import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import DateTimeFormatter from '../../../components/intl/DateTimeFormatter'; import { translate } from '../../../helpers/l10n'; import { ComponentQualifier } from '../../../types/component'; @@ -27,6 +29,7 @@ import { ProjectAnalysisEventCategory, Analysis as TypeAnalysis, } from '../../../types/project-activity'; +import { Status } from '../../../types/types'; import { AnalysisVariations } from './AnalysisVariations'; import Event from './Event'; @@ -34,14 +37,15 @@ export interface AnalysisProps { analysis: TypeAnalysis; isFirstAnalysis?: boolean; qualifier: string; + qualityGateStatus?: string; variations?: AnalysisMeasuresVariations; } export function Analysis(props: Readonly) { - const { analysis, isFirstAnalysis, qualifier, variations } = props; + const { analysis, isFirstAnalysis, qualifier, qualityGateStatus, variations } = props; const sortedEvents = sortBy( - analysis.events, + analysis.events.filter((event) => event.category !== ProjectAnalysisEventCategory.QualityGate), (event) => { switch (event.category) { case ProjectAnalysisEventCategory.Version: @@ -66,8 +70,29 @@ export function Analysis(props: Readonly) { return (
-
- +
+
+ +
+ {qualityGateStatus !== undefined && ( +
+ + ), + }} + /> + + + +
+ )}
{sortedEvents.length > 0 diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx index 0c02104405e..5c83b9abd72 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx @@ -40,7 +40,8 @@ import ActivityPanel, { ActivityPanelProps } from '../ActivityPanel'; it('should render correctly', async () => { renderActivityPanel(); - expect(await screen.findByText('event.quality_gate.ERROR')).toBeInTheDocument(); + expect(await screen.findAllByText('metric.level.ERROR')).toHaveLength(2); + expect(screen.getAllByText('metric.level.OK')).toHaveLength(2); expect(screen.getByRole('status', { name: 'v1.0' })).toBeInTheDocument(); expect(screen.getByText(/event.category.OTHER/)).toBeInTheDocument(); expect(screen.getByText(/event.category.DEFINITION_CHANGE/)).toBeInTheDocument(); @@ -112,6 +113,15 @@ function renderActivityPanel(props: Partial = {}) { mockHistoryItem({ date: parseDate('2020-10-27T18:33:50+0200'), value: '14.2' }), ], }), + mockMeasureHistory({ + metric: MetricKey.alert_status, + history: [ + mockHistoryItem({ date: parseDate('2018-10-27T10:21:15+0200'), value: 'OK' }), + mockHistoryItem({ date: parseDate('2018-10-27T12:21:15+0200'), value: 'ERROR' }), + mockHistoryItem({ date: parseDate('2020-10-27T16:33:50+0200'), value: 'ERROR' }), + mockHistoryItem({ date: parseDate('2020-10-27T18:33:50+0200'), value: 'OK' }), + ], + }), ]; const mockedMetrics = [mockMetric()]; const mockedAnalysis = [ diff --git a/server/sonar-web/src/main/js/apps/overview/utils.ts b/server/sonar-web/src/main/js/apps/overview/utils.ts index 195386a2a1a..d67c362653c 100644 --- a/server/sonar-web/src/main/js/apps/overview/utils.ts +++ b/server/sonar-web/src/main/js/apps/overview/utils.ts @@ -106,6 +106,7 @@ export const HISTORY_METRICS_LIST: string[] = [ MetricKey.duplicated_lines_density, MetricKey.ncloc, MetricKey.coverage, + MetricKey.alert_status, ]; const MEASURES_VARIATIONS_METRICS = [ -- 2.39.5