From 21dc2dcb8b252123dd31eba496d5dde4f28351af Mon Sep 17 00:00:00 2001 From: stanislavh Date: Tue, 23 Jan 2024 11:41:55 +0100 Subject: [PATCH] SONAR-21467 Adopt new 2 column layout for branch overview --- .../branches/BranchOverviewRenderer.tsx | 29 +++++---- .../overview/branches/QualityGatePanel.tsx | 64 ++++++++----------- .../js/apps/overview/branches/TabsPanel.tsx | 22 +++++-- .../branches/__tests__/BranchOverview-it.tsx | 2 +- .../overview/components/LastAnalysisLabel.tsx | 44 +++++++++++++ .../components/QualityGateStatusHeader.tsx | 27 ++++---- .../components/QualityGateStatusTitle.tsx | 25 ++++---- .../pullRequests/PullRequestMetaTopBar.tsx | 15 +---- .../resources/org/sonar/l10n/core.properties | 3 +- 9 files changed, 132 insertions(+), 99 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/overview/components/LastAnalysisLabel.tsx diff --git a/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx b/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx index 0dca8d3241e..9c6e4415766 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx @@ -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 { BasicSeparator, LargeCenteredLayout, PageContentFontWrapper } from 'design-system'; +import { BasicSeparator, Card, LargeCenteredLayout, PageContentFontWrapper } from 'design-system'; import * as React from 'react'; import A11ySkipTarget from '../../../components/a11y/A11ySkipTarget'; import { useLocation } from '../../../components/hoc/withRouter'; @@ -31,6 +31,7 @@ import { Analysis, GraphType, MeasureHistory } from '../../../types/project-acti import { QualityGateStatus } from '../../../types/quality-gates'; import { Component, MeasureEnhanced, Metric, Period, QualityGate } from '../../../types/types'; import { AnalysisStatus } from '../components/AnalysisStatus'; +import SonarLintPromotion from '../components/SonarLintPromotion'; import { MeasuresTabs } from '../utils'; import AcceptedIssuesPanel from './AcceptedIssuesPanel'; import ActivityPanel from './ActivityPanel'; @@ -125,24 +126,30 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp )} -
-
- +
+ + + + qg.failedConditions)} />
-
-
+ +
-
+
)} diff --git a/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx index e621fdc3b32..0118908120d 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { BasicSeparator, Card, Spinner } from 'design-system'; -import { flatMap } from 'lodash'; import * as React from 'react'; import { ComponentQualifier, isApplication } from '../../../types/component'; import { QualityGateStatus } from '../../../types/quality-gates'; @@ -27,7 +26,6 @@ import IgnoredConditionWarning from '../components/IgnoredConditionWarning'; import QualityGateStatusHeader from '../components/QualityGateStatusHeader'; import QualityGateStatusPassedView from '../components/QualityGateStatusPassedView'; import { QualityGateStatusTitle } from '../components/QualityGateStatusTitle'; -import SonarLintPromotion from '../components/SonarLintPromotion'; import ApplicationNonCaycProjectWarning from './ApplicationNonCaycProjectWarning'; import CleanAsYouCodeWarning from './CleanAsYouCodeWarning'; import QualityGatePanelSection from './QualityGatePanelSection'; @@ -71,41 +69,33 @@ export function QualityGatePanel(props: QualityGatePanelProps) { return (
- -
- {loading ? ( -
- +
+ + + {success && } + + {showIgnoredConditionWarning && } + + {!success && } + + {overallFailedConditionsCount > 0 && ( +
+ {failedQgStatuses.map((qgStatus, qgStatusIdx) => ( + + ))}
- ) : ( - <> - - {success && } - - {showIgnoredConditionWarning && } - - {!success && } - - {overallFailedConditionsCount > 0 && ( -
- {failedQgStatuses.map((qgStatus, qgStatusIdx) => ( - - ))} -
- )} - )} -
- +
+
{nonCaycProjectsInApp.length > 0 && ( @@ -119,10 +109,6 @@ export function QualityGatePanel(props: QualityGatePanelProps) { )} - - qgStatus.failedConditions)} - />
); } diff --git a/server/sonar-web/src/main/js/apps/overview/branches/TabsPanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/TabsPanel.tsx index 9756c817ae9..87a370b243b 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/TabsPanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/TabsPanel.tsx @@ -20,6 +20,7 @@ import { isBefore, sub } from 'date-fns'; import { ButtonLink, + CardSeparator, FlagMessage, LightLabel, PageTitle, @@ -27,15 +28,17 @@ import { ToggleButton, } from 'design-system'; import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, useIntl } from 'react-intl'; import DocLink from '../../../components/common/DocLink'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { translate } from '../../../helpers/l10n'; import { isDiffMetric } from '../../../helpers/measures'; import { ApplicationPeriod } from '../../../types/application'; +import { Branch } from '../../../types/branch-like'; import { ComponentQualifier } from '../../../types/component'; import { Analysis, ProjectAnalysisEventCategory } from '../../../types/project-activity'; import { QualityGateStatus } from '../../../types/quality-gates'; import { Component, Period } from '../../../types/types'; +import LastAnalysisLabel from '../components/LastAnalysisLabel'; import { MeasuresTabs } from '../utils'; import { MAX_ANALYSES_NB } from './ActivityPanel'; import { LeakPeriodInfo } from './LeakPeriodInfo'; @@ -46,6 +49,7 @@ export interface MeasuresPanelProps { component: Component; loading?: boolean; period?: Period; + branch?: Branch; qgStatuses?: QualityGateStatus[]; isNewCode: boolean; onTabSelect: (tab: MeasuresTabs) => void; @@ -62,9 +66,10 @@ export function TabsPanel(props: React.PropsWithChildren) { period, qgStatuses = [], isNewCode, + branch, children, } = props; - + const intl = useIntl(); const isApp = component.qualifier === ComponentQualifier.Application; const leakPeriod = isApp ? appLeak : period; @@ -124,9 +129,11 @@ export function TabsPanel(props: React.PropsWithChildren) { return (
-
+
+
+ {loading ? (
@@ -160,9 +167,10 @@ export function TabsPanel(props: React.PropsWithChildren) { /> {failingConditions > 0 && ( - {failingConditions === 1 - ? translate('overview.1_condition_failed') - : translateWithParameters('overview.X_conditions_failed', failingConditions)} + {intl.formatMessage( + { id: 'overview.X_conditions_failed' }, + { conditions: failingConditions }, + )} )}
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx index b06c4671c1e..75e12de4e5c 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx @@ -308,7 +308,7 @@ describe('project overview', () => { renderBranchOverview(); expect(await screen.findByText('metric.level.ERROR')).toBeInTheDocument(); - expect(screen.getAllByText('overview.X_conditions_failed.2')).toHaveLength(2); + expect(screen.getAllByText(/overview.X_conditions_failed/)).toHaveLength(2); }); it('should correctly show a project as empty', async () => { diff --git a/server/sonar-web/src/main/js/apps/overview/components/LastAnalysisLabel.tsx b/server/sonar-web/src/main/js/apps/overview/components/LastAnalysisLabel.tsx new file mode 100644 index 00000000000..5fcb961d0f3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/components/LastAnalysisLabel.tsx @@ -0,0 +1,44 @@ +/* + * 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 React from 'react'; +import { useIntl } from 'react-intl'; +import DateFromNow from '../../../components/intl/DateFromNow'; + +interface Props { + analysisDate?: string; +} + +export default function LastAnalysisLabel({ analysisDate }: Readonly) { + const intl = useIntl(); + + return analysisDate ? ( + + {intl.formatMessage( + { + id: 'overview.last_analysis_x', + }, + { + date: , + }, + )} + + ) : null; +} diff --git a/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusHeader.tsx b/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusHeader.tsx index 7b0358799b2..c4eee2fd3ae 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusHeader.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusHeader.tsx @@ -17,9 +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, TextError, TextMuted } from 'design-system'; +import { QualityGateIndicator, TextError } from 'design-system'; import React from 'react'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { useIntl } from 'react-intl'; +import { translate } from '../../../helpers/l10n'; import { Status } from '../../../types/types'; interface Props { @@ -29,26 +30,22 @@ interface Props { export default function QualityGateStatusHeader(props: Props) { const { status, failedConditionCount } = props; + const intl = useIntl(); return (
-
- -
-
- {translate('metric.level', status)} -
-
-
+ {translate('metric.level', status)} {failedConditionCount > 0 && ( {failedConditionCount}, + }, + )} /> )}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusTitle.tsx b/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusTitle.tsx index 57bc32771a0..4e2e543581c 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusTitle.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/QualityGateStatusTitle.tsx @@ -17,23 +17,26 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { HelperHintIcon, PageTitle } from 'design-system'; +import { CardSeparator, HelperHintIcon, PageTitle } from 'design-system'; import React from 'react'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import { translate } from '../../../helpers/l10n'; export function QualityGateStatusTitle() { return ( -
-
- - {translate('overview.quality_gate.help')}
} - > - - + <> +
+
+ + {translate('overview.quality_gate.help')}
} + > + + +
-
+ + ); } diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestMetaTopBar.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestMetaTopBar.tsx index 72c4a6a35cc..0ce4a8aae1f 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestMetaTopBar.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestMetaTopBar.tsx @@ -21,12 +21,12 @@ import { SeparatorCircleIcon } from 'design-system'; import React from 'react'; import { useIntl } from 'react-intl'; import CurrentBranchLikeMergeInformation from '../../../app/components/nav/component/branch-like/CurrentBranchLikeMergeInformation'; -import DateFromNow from '../../../components/intl/DateFromNow'; import { getLeakValue } from '../../../components/measure/utils'; import { findMeasure, formatMeasure } from '../../../helpers/measures'; import { PullRequest } from '../../../types/branch-like'; import { MetricKey, MetricType } from '../../../types/metrics'; import { MeasureEnhanced } from '../../../types/types'; +import LastAnalysisLabel from '../components/LastAnalysisLabel'; interface Props { pullRequest: PullRequest; @@ -54,18 +54,7 @@ export default function PullRequestMetaTopBar({ pullRequest, measures }: Readonl {pullRequest.analysisDate && ( <> - {intl.formatMessage( - { - id: 'overview.last_analysis_x', - }, - { - date: ( - - - - ), - }, - )} + )}
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 2d31837134b..c48bc626eda 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3848,8 +3848,7 @@ system.version_is_availble={version} is available # OVERVIEW # #------------------------------------------------------------------------------ -overview.1_condition_failed=1 failed condition -overview.X_conditions_failed={0} failed conditions +overview.X_conditions_failed={conditions} {conditions, plural, one {failed condition} other {failed conditions}} overview.failed_condition.x_rating_required={rating} is {value}. Required {threshold} overview.failed_condition.x_required={metric}. Required {threshold} overview.fix_failed_conditions_with_sonarlint=Fix issues before they fail your Quality Gate with {link} in your IDE. Power up with connected mode! -- 2.39.5