aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorstanislavh <stanislav.honcharov@sonarsource.com>2024-12-03 14:00:53 +0100
committersonartech <sonartech@sonarsource.com>2024-12-04 20:03:23 +0000
commit8b42a96a0d85de0a88667c0881ba3df7a9dab3c0 (patch)
tree1500e29891eeb3a6ebd2a2cdbb6038f429a6e9fd /server/sonar-web
parent79b3fc224ffa57b1e0be55600713c577d376ba5f (diff)
downloadsonarqube-8b42a96a0d85de0a88667c0881ba3df7a9dab3c0.tar.gz
sonarqube-8b42a96a0d85de0a88667c0881ba3df7a9dab3c0.zip
SONAR-23666 Improve accessibility by informing the user of link destination
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/__mocks__/react-intl.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Header.tsx26
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx30
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/AnalysisScope.tsx62
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/DefinitionDescription.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx14
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/__tests__/AnalysisScope-test.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/shared/CleanCodeAttributePill.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/shared/SoftwareImpactPill.tsx4
-rw-r--r--server/sonar-web/src/main/js/helpers/doc-links.ts2
12 files changed, 115 insertions, 51 deletions
diff --git a/server/sonar-web/__mocks__/react-intl.tsx b/server/sonar-web/__mocks__/react-intl.tsx
index f68d0c36c3f..d3c6366be5d 100644
--- a/server/sonar-web/__mocks__/react-intl.tsx
+++ b/server/sonar-web/__mocks__/react-intl.tsx
@@ -30,7 +30,7 @@ module.exports = {
{id}
{Object.entries(values).map(([key, value]) => (
<React.Fragment key={key}>
- {typeof value === 'function' ? value() : value}
+ {typeof value === 'function' ? value(`${id}_${key}`) : value}
</React.Fragment>
))}
</>
@@ -45,7 +45,7 @@ module.exports = {
values,
}: {
id: string;
- values?: { [x: string]: React.ReactNode | (() => React.ReactNode) };
+ values?: { [x: string]: React.ReactNode | ((text: string) => React.ReactNode) };
}) => {
return (
<>
@@ -53,7 +53,7 @@ module.exports = {
{values !== undefined &&
Object.entries(values).map(([key, value]) => (
<React.Fragment key={key}>
- {typeof value === 'function' ? value() : value}
+ {typeof value === 'function' ? value(`${id}_${key}`) : value}
</React.Fragment>
))}
</>
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Header.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/Header.tsx
index 5e3460e49d9..0a677474771 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/Header.tsx
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Header.tsx
@@ -18,7 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { Title } from '~design-system';
+import { Heading, LinkHighlight } from '@sonarsource/echoes-react';
+import { useIntl } from 'react-intl';
import DocumentationLink from '../../../components/common/DocumentationLink';
import { DocLink } from '../../../helpers/doc-links';
import { translate } from '../../../helpers/l10n';
@@ -30,15 +31,28 @@ interface Props {
}
export default function Header(props: Readonly<Props>) {
+ const intl = useIntl();
return (
<header className="sw-mb-12 sw-flex sw-justify-between">
<div className="sw-flex-1">
- <Title className="sw-mb-4">{translate('background_tasks.page')}</Title>
+ <Heading as="h2" className="sw-mb-4">
+ {translate('background_tasks.page')}
+ </Heading>
<p className="sw-max-w-3/4">
- {translate('background_tasks.page.description')}
- <DocumentationLink className="sw-ml-2" to={DocLink.BackgroundTasks}>
- {translate('learn_more')}
- </DocumentationLink>
+ {intl.formatMessage(
+ { id: 'background_tasks.page.description' },
+ {
+ link: (text) => (
+ <DocumentationLink
+ shouldOpenInNewTab
+ highlight={LinkHighlight.CurrentColor}
+ to={DocLink.BackgroundTasks}
+ >
+ {text}
+ </DocumentationLink>
+ ),
+ },
+ )}
</p>
</div>
{!props.component && (
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx
index c78f88b41c6..b760ff90556 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx
@@ -68,8 +68,8 @@ export default function ListHeader({ canCreate }: Readonly<Props>) {
title={intl.formatMessage({ id: 'quality_gates.help.title' })}
description={intl.formatMessage({ id: 'quality_gates.help.desc' })}
footer={
- <DocumentationLink standalone to={DocLink.QualityGates}>
- {intl.formatMessage({ id: 'learn_more' })}
+ <DocumentationLink shouldOpenInNewTab standalone to={DocLink.QualityGates}>
+ {intl.formatMessage({ id: 'quality_gates.help.link' })}
</DocumentationLink>
}
>
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx
index 5d89c56814c..aa29b7e493d 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx
@@ -18,14 +18,20 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { Button, ButtonGroup, ButtonVariety, Heading, Link } from '@sonarsource/echoes-react';
+import {
+ Button,
+ ButtonGroup,
+ ButtonVariety,
+ Heading,
+ LinkHighlight,
+} from '@sonarsource/echoes-react';
import * as React from 'react';
import { useIntl } from 'react-intl';
import { FlagMessage } from '~design-system';
import { useLocation, useRouter } from '~sonar-aligned/components/hoc/withRouter';
import { Actions } from '../../../api/quality-profiles';
+import DocumentationLink from '../../../components/common/DocumentationLink';
import { DocLink } from '../../../helpers/doc-links';
-import { useDocUrl } from '../../../helpers/docs';
import { translate } from '../../../helpers/l10n';
import { Profile } from '../types';
import { getProfilePath } from '../utils';
@@ -44,7 +50,6 @@ export default function PageHeader(props: Readonly<Props>) {
const intl = useIntl();
const location = useLocation();
const router = useRouter();
- const docUrl = useDocUrl(DocLink.InstanceAdminQualityProfiles);
const [modal, setModal] = React.useState<'' | 'createProfile' | 'restoreProfile'>('');
@@ -67,11 +72,20 @@ export default function PageHeader(props: Readonly<Props>) {
</Heading>
<div className="sw-typo-default">
- {intl.formatMessage({ id: 'quality_profiles.intro' })}
-
- <Link className="sw-ml-2" to={docUrl}>
- {intl.formatMessage({ id: 'learn_more' })}
- </Link>
+ {intl.formatMessage(
+ { id: 'quality_profiles.intro' },
+ {
+ link: (text) => (
+ <DocumentationLink
+ shouldOpenInNewTab
+ to={DocLink.InstanceAdminQualityProfiles}
+ highlight={LinkHighlight.CurrentColor}
+ >
+ {text}
+ </DocumentationLink>
+ ),
+ },
+ )}
</div>
</div>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/AnalysisScope.tsx b/server/sonar-web/src/main/js/apps/settings/components/AnalysisScope.tsx
index 49525b34f73..bc7bee86eac 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/AnalysisScope.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/AnalysisScope.tsx
@@ -19,7 +19,8 @@
*/
import styled from '@emotion/styled';
-import { LightLabel } from '~design-system';
+import { Heading, LinkHighlight, Text } from '@sonarsource/echoes-react';
+import { useIntl } from 'react-intl';
import DocumentationLink from '../../../components/common/DocumentationLink';
import { DocLink } from '../../../helpers/doc-links';
import { translate } from '../../../helpers/l10n';
@@ -28,28 +29,57 @@ import CategoryDefinitionsList from './CategoryDefinitionsList';
export function AnalysisScope(props: AdditionalCategoryComponentProps) {
const { component, definitions, selectedCategory } = props;
+ const intl = useIntl();
return (
<>
- <StyledGrid className="sw-pt-6 sw-px-6 sw-gap-2">
- <p className="sw-col-span-2">
- {translate('settings.analysis_scope.wildcards.introduction')}
- </p>
+ <StyledGrid className="sw-pt-1 sw-px-1 sw-gap-2">
+ <Heading as="h2" className="sw-col-span-2">
+ {translate('property.category.exclusions')}
+ </Heading>
- <span>*</span>
- <LightLabel>{translate('settings.analysis_scope.wildcards.zero_more_char')}</LightLabel>
+ <Text className="sw-col-span-2 sw-mt-4 sw-mb-3">
+ {intl.formatMessage(
+ { id: 'settings.analysis_scope.introduction' },
+ {
+ link: (text) => (
+ <DocumentationLink
+ shouldOpenInNewTab
+ highlight={LinkHighlight.CurrentColor}
+ to={DocLink.AnalysisScopeWildcardPatterns}
+ >
+ {text}
+ </DocumentationLink>
+ ),
+ },
+ )}
+ </Text>
- <span>**</span>
- <LightLabel>{translate('settings.analysis_scope.wildcards.zero_more_dir')}</LightLabel>
+ <Text as="p" className="sw-col-span-2">
+ {intl.formatMessage(
+ { id: 'settings.analysis_scope.wildcards.introduction' },
+ {
+ link: (text) => (
+ <DocumentationLink
+ shouldOpenInNewTab
+ highlight={LinkHighlight.CurrentColor}
+ to={DocLink.AnalysisScope}
+ >
+ {text}
+ </DocumentationLink>
+ ),
+ },
+ )}
+ </Text>
- <span>?</span>
- <LightLabel>{translate('settings.analysis_scope.wildcards.single_char')}</LightLabel>
+ <Text>*</Text>
+ <Text isSubdued>{translate('settings.analysis_scope.wildcards.zero_more_char')}</Text>
- <div className="sw-col-span-2">
- <DocumentationLink to={DocLink.AnalysisScope}>
- {translate('settings.analysis_scope.learn_more')}
- </DocumentationLink>
- </div>
+ <Text>**</Text>
+ <Text isSubdued>{translate('settings.analysis_scope.wildcards.zero_more_dir')}</Text>
+
+ <Text>?</Text>
+ <Text isSubdued>{translate('settings.analysis_scope.wildcards.single_char')}</Text>
</StyledGrid>
<CategoryDefinitionsList
diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDescription.tsx b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDescription.tsx
index 6afc913924e..ec6188bc0b2 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDescription.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDescription.tsx
@@ -18,8 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { Text, Tooltip } from '@sonarsource/echoes-react';
-import { SafeHTMLInjection, SanitizeLevel, SubHeading } from '~design-system';
+import { Heading, Text, Tooltip } from '@sonarsource/echoes-react';
+import { SafeHTMLInjection, SanitizeLevel } from '~design-system';
import { translateWithParameters } from '../../../helpers/l10n';
import { ExtendedSettingDefinition } from '../../../types/settings';
import { getPropertyDescription, getPropertyName } from '../utils';
@@ -34,9 +34,9 @@ export default function DefinitionDescription({ definition }: Readonly<Props>) {
return (
<div className="sw-w-abs-300">
- <SubHeading className="sw-text-ellipsis sw-overflow-hidden" title={propertyName}>
+ <Heading as="h4" className="sw-text-ellipsis sw-overflow-hidden">
{propertyName}
- </SubHeading>
+ </Heading>
{description && (
<SafeHTMLInjection htmlAsString={description} sanitizeLevel={SanitizeLevel.RESTRICTED}>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx
index 6a9f88834e8..bf9d5b732ce 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx
@@ -18,9 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { Heading } from '@sonarsource/echoes-react';
+import classNames from 'classnames';
import { groupBy, sortBy } from 'lodash';
import * as React from 'react';
-import { BasicSeparator, Note, SafeHTMLInjection, SanitizeLevel, SubTitle } from '~design-system';
+import { BasicSeparator, Note, SafeHTMLInjection, SanitizeLevel } from '~design-system';
import { withRouter } from '~sonar-aligned/components/hoc/withRouter';
import { Location } from '~sonar-aligned/types/router';
import { SettingDefinitionAndValue } from '../../../types/settings';
@@ -81,17 +83,17 @@ class SubCategoryDefinitionsList extends React.PureComponent<SubCategoryDefiniti
: sortedSubCategories.filter((c) => !SUB_CATEGORY_EXCLUSIONS[category]?.includes(c.key));
return (
- <ul>
+ <ul className={classNames({ 'sw-mx-6': !noPadding })}>
{filteredSubCategories.map((subCategory, index) => (
- <li className={noPadding ? '' : 'sw-p-6'} key={subCategory.key}>
+ <li className={classNames({ 'sw-py-6': !noPadding })} key={subCategory.key}>
{displaySubCategoryTitle && (
- <SubTitle
- as="h2"
+ <Heading
+ as="h3"
data-key={subCategory.key}
ref={this.scrollToSubCategoryOrDefinition}
>
{subCategory.name}
- </SubTitle>
+ </Heading>
)}
{subCategory.description != null && (
diff --git a/server/sonar-web/src/main/js/apps/settings/components/__tests__/AnalysisScope-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/__tests__/AnalysisScope-test.tsx
index dfc9e4c9a83..96807c96a7f 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/__tests__/AnalysisScope-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/__tests__/AnalysisScope-test.tsx
@@ -32,7 +32,9 @@ const handler = new SettingsServiceMock();
const ui = {
introduction: byText('settings.analysis_scope.wildcards.introduction'),
- docLink: byRole('link', { name: /learn_more/ }),
+ docLink: byRole('link', {
+ name: 'settings.analysis_scope.wildcards.introduction_link open_in_new_tab',
+ }),
};
beforeEach(() => {
diff --git a/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx b/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx
index e125d76f9c9..b516cabe002 100644
--- a/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx
+++ b/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx
@@ -62,8 +62,8 @@ export default function SeverityFacet(props: Readonly<BasicProps>) {
{ id: `severity_impact.help.description` },
{ p1: (text) => <p>{text}</p>, p: (text) => <p className="sw-mt-4">{text}</p> },
)}
- link={DocLink.CleanCodeIntroduction}
- linkText={intl.formatMessage({ id: 'learn_more' })}
+ link={DocLink.MQRSeverity}
+ linkText={intl.formatMessage({ id: 'severity_impact.help.link' })}
/>
)
}
diff --git a/server/sonar-web/src/main/js/components/shared/CleanCodeAttributePill.tsx b/server/sonar-web/src/main/js/components/shared/CleanCodeAttributePill.tsx
index 3f45f75d7d6..b418e39d953 100644
--- a/server/sonar-web/src/main/js/components/shared/CleanCodeAttributePill.tsx
+++ b/server/sonar-web/src/main/js/components/shared/CleanCodeAttributePill.tsx
@@ -51,7 +51,7 @@ export function CleanCodeAttributePill(props: Readonly<Props>) {
)}
footer={
<DocumentationLink to={DocLink.CleanCodeIntroduction}>
- {translate('learn_more')}
+ {translate('clean_code_attribute.learn_more')}
</DocumentationLink>
}
>
diff --git a/server/sonar-web/src/main/js/components/shared/SoftwareImpactPill.tsx b/server/sonar-web/src/main/js/components/shared/SoftwareImpactPill.tsx
index 43fb6dd9856..ec6578de8c3 100644
--- a/server/sonar-web/src/main/js/components/shared/SoftwareImpactPill.tsx
+++ b/server/sonar-web/src/main/js/components/shared/SoftwareImpactPill.tsx
@@ -144,8 +144,8 @@ export default function SoftwareImpactPill(props: Props) {
</>
}
footer={
- <DocumentationLink to={DocLink.CleanCodeIntroduction}>
- {translate('learn_more')}
+ <DocumentationLink shouldOpenInNewTab to={DocLink.MQRSeverity}>
+ {translate('severity_impact.help.link')}
</DocumentationLink>
}
>
diff --git a/server/sonar-web/src/main/js/helpers/doc-links.ts b/server/sonar-web/src/main/js/helpers/doc-links.ts
index 393dcbea3e2..ca747817d8e 100644
--- a/server/sonar-web/src/main/js/helpers/doc-links.ts
+++ b/server/sonar-web/src/main/js/helpers/doc-links.ts
@@ -45,6 +45,7 @@ export enum DocLink {
AlmSamlAuth = '/instance-administration/authentication/saml/overview/',
AlmSamlScimAuth = '/instance-administration/authentication/saml/scim/overview/',
AnalysisScope = '/project-administration/analysis-scope/',
+ AnalysisScopeWildcardPatterns = '/project-administration/analysis-scope/#wildcard-patterns',
AuthOverview = '/instance-administration/authentication/overview/',
BackgroundTasks = '/analyzing-source-code/background-tasks/',
BranchAnalysis = '/analyzing-source-code/branch-analysis/introduction/',
@@ -83,6 +84,7 @@ export enum DocLink {
QualityGates = '/instance-administration/analysis-functions/quality-gates/',
Root = '/',
RuleSeverity = '/instance-administration/analysis-functions/quality-profiles/#rule-severity',
+ MQRSeverity = '/instance-administration/analysis-functions/instance-mode/mqr-mode/#mqr-severity',
RulesOverview = '/user-guide/rules/overview',
SecurityHotspots = '/user-guide/security-hotspots/',
SecurityReports = '/user-guide/viewing-reports/security-reports/',