${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')};
`;
return (
<>
- <span className="spacer-right">{translate('indexation.in_progress')}</span>
+ <span className="spacer-right">{`${translate('indexation.in_progress')} ${translate(
+ 'indexation.projects_unavailable'
+ )}`}</span>
<i className="spinner spacer-right" />
<span className="spacer-right">
{translateWithParameters('indexation.progression', percentCompleted)}
return (
<>
- <span className="spacer-right">{translate('indexation.in_progress')}</span>
+ <span className="spacer-right">{`${translate('indexation.in_progress')} ${translate(
+ 'indexation.projects_unavailable'
+ )}`}</span>
<i className="spinner spacer-right" />
<span className="spacer-right">
<FormattedMessage
<span
className="spacer-right"
>
- indexation.in_progress
+ indexation.in_progress indexation.projects_unavailable
</span>
<i
className="spinner spacer-right"
<span
className="spacer-right"
>
- indexation.in_progress
+ indexation.in_progress indexation.projects_unavailable
</span>
<i
className="spinner spacer-right"
<span
className="spacer-right"
>
- indexation.in_progress
+ indexation.in_progress indexation.projects_unavailable
</span>
<i
className="spinner spacer-right"
<span
className="spacer-right"
>
- indexation.in_progress
+ indexation.in_progress indexation.projects_unavailable
</span>
<i
className="spinner spacer-right"
CoverageIndicator,
DeferredSpinner,
DuplicationsIndicator,
+ FlagMessage,
LightLabel,
PageTitle,
ToggleButton,
} from 'design-system';
import * as React from 'react';
+import DocLink from '../../../components/common/DocLink';
import ComponentReportActions from '../../../components/controls/ComponentReportActions';
import { Location, withRouter } from '../../../components/hoc/withRouter';
import { duplicationRatingConverter } from '../../../components/measure/utils';
</LightLabel>
)}
</div>
-
{tab === MeasuresPanelTabs.New && leakPeriod ? (
<LightLabel className="sw-body-sm sw-flex sw-items-center sw-mt-4">
<span className="sw-mr-1">{translate('overview.new_code')}:</span>
<div className="sw-h-4 sw-pt-1 sw-mt-4" />
)}
+ {component.qualifier === ComponentQualifier.Application && component.needIssueSync && (
+ <FlagMessage className="sw-mt-4" variant="info">
+ <span>
+ {`${translate('indexation.in_progress')} ${translate(
+ 'indexation.details_unavailable'
+ )}`}
+ <DocLink
+ className="sw-ml-1 sw-whitespace-nowrap"
+ to="/instance-administration/reindexing/"
+ >
+ {translate('learn_more')}
+ </DocLink>
+ </span>
+ </FlagMessage>
+ )}
+
{!hasDiffMeasures && isNewCodeTab ? (
<MeasuresPanelNoNewCode branch={branch} component={component} period={period} />
) : (
* 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;
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 =
? 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 (
<div className="sw-body-md sw-flex sw-items-center">
{value === undefined ? (
<LightLabel aria-label={translate('no_data')}> — </LightLabel>
) : (
- <DrilldownLink
- aria-label={translateWithParameters(
- 'overview.see_list_of_x_y_issues',
- value,
- localizeMetric(metricKey)
- )}
- className="it__overview-measures-value"
- to={url}
+ <Tooltip
+ classNameSpace={disabled ? 'tooltip' : 'sw-hidden'}
+ overlay={<OverviewDisabledLinkTooltip />}
>
- {formatMeasure(value, MetricType.ShortInteger)}
- </DrilldownLink>
+ <DrilldownLink className="it__overview-measures-value" {...drilldownLinkProps}>
+ {formatMeasure(value, MetricType.ShortInteger)}
+ </DrilldownLink>
+ </Tooltip>
)}
+
<LightLabel className="sw-mx-2">{localizeMetric(metricKey)}</LightLabel>
+
{helpTooltip && (
<HelpTooltip overlay={helpTooltip}>
<HelperHintIcon aria-label={helpTooltip} />
--- /dev/null
+/*
+ * 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 (
+ <div className="sw-body-sm sw-w-[280px]">
+ {translate('indexation.in_progress')}
+
+ <br />
+
+ {translate('indexation.link_unavailable')}
+
+ <hr className="sw-mx-0 sw-my-3 sw-p-0 sw-w-full" />
+
+ <span className="sw-body-sm-highlight">{translate('indexation.learn_more')}</span>
+
+ <DocLink className="sw-ml-1" to="/instance-administration/reindexing/">
+ {translate('indexation.reindexing')}
+ </DocLink>
+ </div>
+ );
+}
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';
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<IssueLabelProps> = {}) {
return renderComponent(
<IssueLabel
# INDEXATION
#
#------------------------------------------------------------------------------
-indexation.in_progress=SonarQube is reloading project data. Some projects will be unavailable until this process is complete.
+indexation.in_progress=SonarQube is reindexing project data.
+indexation.details_unavailable=Details are unavailable until this process is complete.
+indexation.link_unavailable=The link to these results is unavailable until this process is complete.
+indexation.projects_unavailable=Some projects will be unavailable until this process is complete.
indexation.progression={0}% complete.
indexation.progression_with_error={0}% complete with some {link}.
indexation.progression_with_error.link=tasks failing