From 913ec5ef5d3b60cf300ebde20795a87e13150242 Mon Sep 17 00:00:00 2001 From: David Cho-Lerat Date: Tue, 18 Jul 2023 16:46:46 +0200 Subject: [PATCH] SONAR-19752 New UX for App overview while re-indexing --- .../design-system/src/components/Link.tsx | 10 +++-- .../IndexationNotificationRenderer.tsx | 8 +++- ...dexationNotificationRenderer-test.tsx.snap | 8 ++-- .../apps/overview/branches/MeasuresPanel.tsx | 19 +++++++- .../apps/overview/components/IssueLabel.tsx | 40 ++++++++++++----- .../OverviewDisabledLinkTooltip.tsx | 43 +++++++++++++++++++ .../components/__tests__/IssueLabel-test.tsx | 21 +++++++++ .../resources/org/sonar/l10n/core.properties | 5 ++- 8 files changed, 132 insertions(+), 22 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/overview/components/OverviewDisabledLinkTooltip.tsx diff --git a/server/sonar-web/design-system/src/components/Link.tsx b/server/sonar-web/design-system/src/components/Link.tsx index 7ec8470de21..02889e25c5f 100644 --- a/server/sonar-web/design-system/src/components/Link.tsx +++ b/server/sonar-web/design-system/src/components/Link.tsx @@ -148,9 +148,13 @@ export const DrilldownLink = styled(StyledBaseLink)` ${tw`sw-tracking-tight`} ${tw`sw-whitespace-nowrap`} - --active: ${themeColor('linkActive')}; - --border: ${themeBorder('default', 'drilldownBorder')}; - --borderActive: ${themeBorder('default', 'linkActive')}; + ${({ disabled, theme }) => + disabled + ? tw`sw-cursor-default` + : `--active: ${themeColor('linkActive')({ theme })}; + --border: ${themeBorder('default', 'drilldownBorder')({ theme })}; + --borderActive: ${themeBorder('default', 'linkActive')({ theme })};`}; + --color: ${themeColor('drilldown')}; `; diff --git a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx index defc97b7527..924963867ae 100644 --- a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx +++ b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx @@ -95,7 +95,9 @@ function renderInProgressBanner(props: IndexationNotificationRendererProps) { return ( <> - {translate('indexation.in_progress')} + {`${translate('indexation.in_progress')} ${translate( + 'indexation.projects_unavailable' + )}`} {translateWithParameters('indexation.progression', percentCompleted)} @@ -120,7 +122,9 @@ function renderInProgressWithFailureBanner(props: IndexationNotificationRenderer return ( <> - {translate('indexation.in_progress')} + {`${translate('indexation.in_progress')} ${translate( + 'indexation.projects_unavailable' + )}`} - indexation.in_progress + indexation.in_progress indexation.projects_unavailable - indexation.in_progress + indexation.in_progress indexation.projects_unavailable - indexation.in_progress + indexation.in_progress indexation.projects_unavailable - indexation.in_progress + indexation.in_progress indexation.projects_unavailable )} - {tab === MeasuresPanelTabs.New && leakPeriod ? ( {translate('overview.new_code')}: @@ -147,6 +148,22 @@ export function MeasuresPanel(props: MeasuresPanelProps) {
)} + {component.qualifier === ComponentQualifier.Application && component.needIssueSync && ( + + + {`${translate('indexation.in_progress')} ${translate( + 'indexation.details_unavailable' + )}`} + + {translate('learn_more')} + + + + )} + {!hasDiffMeasures && isNewCodeTab ? ( ) : ( diff --git a/server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx b/server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx index 511cf069cb2..baf7b512cde 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx @@ -17,19 +17,23 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + import { DrilldownLink, HelperHintIcon, LightLabel } from 'design-system'; import * as React from 'react'; import HelpTooltip from '../../../components/controls/HelpTooltip'; +import Tooltip from '../../../components/controls/Tooltip'; import { getLeakValue } from '../../../components/measure/utils'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { findMeasure, formatMeasure, localizeMetric } from '../../../helpers/measures'; import { getComponentIssuesUrl, getComponentSecurityHotspotsUrl } from '../../../helpers/urls'; import { BranchLike } from '../../../types/branch-like'; +import { ComponentQualifier } from '../../../types/component'; import { IssueType } from '../../../types/issues'; import { MetricType } from '../../../types/metrics'; import { Component, MeasureEnhanced } from '../../../types/types'; import { getIssueMetricKey } from '../utils'; +import { OverviewDisabledLinkTooltip } from './OverviewDisabledLinkTooltip'; export interface IssueLabelProps { branchLike?: BranchLike; @@ -46,15 +50,16 @@ export function IssueLabel(props: IssueLabelProps) { const measure = findMeasure(measures, metricKey); let value; + if (measure) { value = useDiffMetric ? getLeakValue(measure) : measure.value; } const params = { ...getBranchLikeQuery(branchLike), + inNewCodePeriod: useDiffMetric ? 'true' : 'false', resolved: 'false', types: type, - inNewCodePeriod: useDiffMetric ? 'true' : 'false', }; const url = @@ -62,24 +67,37 @@ export function IssueLabel(props: IssueLabelProps) { ? getComponentSecurityHotspotsUrl(component.key, params) : getComponentIssuesUrl(component.key, params); + const disabled = + component.qualifier === ComponentQualifier.Application && component.needIssueSync; + + const drilldownLinkProps = disabled + ? { disabled, to: '' } + : { + 'aria-label': translateWithParameters( + 'overview.see_list_of_x_y_issues', + value as string, + localizeMetric(metricKey) + ), + to: url, + }; + return (
{value === undefined ? ( — ) : ( - } > - {formatMeasure(value, MetricType.ShortInteger)} - + + {formatMeasure(value, MetricType.ShortInteger)} + + )} + {localizeMetric(metricKey)} + {helpTooltip && ( diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewDisabledLinkTooltip.tsx b/server/sonar-web/src/main/js/apps/overview/components/OverviewDisabledLinkTooltip.tsx new file mode 100644 index 00000000000..1242d472b13 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewDisabledLinkTooltip.tsx @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 * as React from 'react'; +import DocLink from '../../../components/common/DocLink'; +import { translate } from '../../../helpers/l10n'; + +export function OverviewDisabledLinkTooltip() { + return ( +
+ {translate('indexation.in_progress')} + +
+ + {translate('indexation.link_unavailable')} + +
+ + {translate('indexation.learn_more')} + + + {translate('indexation.reindexing')} + +
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx index 6d2de23747f..5b2746e3621 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx @@ -23,6 +23,7 @@ import { mockPullRequest } from '../../../../helpers/mocks/branch-like'; import { mockComponent } from '../../../../helpers/mocks/component'; import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks'; import { renderComponent } from '../../../../helpers/testReactTestingUtils'; +import { ComponentQualifier } from '../../../../types/component'; import { IssueType } from '../../../../types/issues'; import { MetricKey } from '../../../../types/metrics'; import { IssueLabel, IssueLabelProps } from '../IssueLabel'; @@ -74,6 +75,26 @@ it('should render correctly for hotspots with tooltip', async () => { expect(screen.getByText('tooltip text')).toBeInTheDocument(); }); +it('should render correctly for a re-indexing Application', () => { + const type = IssueType.SecurityHotspot; + const measures = [ + mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.security_hotspots }) }), + mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_security_hotspots }) }), + ]; + + renderIssueLabel({ + component: mockComponent({ needIssueSync: true, qualifier: ComponentQualifier.Application }), + measures, + type, + }); + + expect( + screen.queryByRole('link', { + name: 'overview.see_list_of_x_y_issues.1.0.metric.security_hotspots.name', + }) + ).not.toBeInTheDocument(); +}); + function renderIssueLabel(props: Partial = {}) { return renderComponent(