aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Silva <kevin.silva@sonarsource.com>2023-01-10 14:41:42 +0100
committersonartech <sonartech@sonarsource.com>2023-01-16 20:03:43 +0000
commit4b10923c40d03bf25fff9cb1bcd92ae15db567ce (patch)
tree32d430b5cc32adcd2a57a2ce88c4aec439bacd39
parent3940b153fe70a090dd1bc6c44ab3c43e2727cbb1 (diff)
downloadsonarqube-4b10923c40d03bf25fff9cb1bcd92ae15db567ce.tar.gz
sonarqube-4b10923c40d03bf25fff9cb1bcd92ae15db567ce.zip
SONAR-17845 [1096026, 1099611] Multiple links have the same programmatic link text but different destinations
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/SimilarRulesFilter.tsx97
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/SimilarRulesFilter-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/SimilarRulesFilter-test.tsx.snap65
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/styles.css16
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties4
5 files changed, 103 insertions, 81 deletions
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/SimilarRulesFilter.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/SimilarRulesFilter.tsx
index 0c3f8e462ea..73fc930e32f 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/SimilarRulesFilter.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/SimilarRulesFilter.tsx
@@ -17,14 +17,16 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import classNames from 'classnames';
import * as React from 'react';
+import { Button, ButtonPlain } from '../../../components/controls/buttons';
import Dropdown from '../../../components/controls/Dropdown';
import DropdownIcon from '../../../components/icons/DropdownIcon';
import FilterIcon from '../../../components/icons/FilterIcon';
import IssueTypeIcon from '../../../components/icons/IssueTypeIcon';
import TagsIcon from '../../../components/icons/TagsIcon';
import SeverityHelper from '../../../components/shared/SeverityHelper';
-import { translate } from '../../../helpers/l10n';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
import { Rule } from '../../../types/types';
import { Query } from '../query';
@@ -34,32 +36,23 @@ interface Props {
}
export default class SimilarRulesFilter extends React.PureComponent<Props> {
- handleLanguageClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
+ handleLanguageClick = () => {
if (this.props.rule.lang) {
this.props.onFilterChange({ languages: [this.props.rule.lang] });
}
};
- handleTypeClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
+ handleTypeClick = () => {
this.props.onFilterChange({ types: [this.props.rule.type] });
};
- handleSeverityClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
+ handleSeverityClick = () => {
if (this.props.rule.severity) {
this.props.onFilterChange({ severities: [this.props.rule.severity] });
}
};
- handleTagClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- event.currentTarget.blur();
- const { tag } = event.currentTarget.dataset;
+ handleTagClick = (tag: string) => {
if (tag) {
this.props.onFilterChange({ tags: [tag] });
}
@@ -75,70 +68,82 @@ export default class SimilarRulesFilter extends React.PureComponent<Props> {
className="display-inline-block"
overlay={
<>
- <h2 className="menu-header" id="filter-similar-rules">
+ <h3 className="coding-rules-filter-title">
{translate('coding_rules.filter_similar_rules')}
- </h2>
- <ul className="menu" aria-labelledby="filter-similar-rules">
- <li>
- <a
- data-test="coding-rules__similar-language"
- href="#"
- onClick={this.handleLanguageClick}
- >
- {rule.langName}
- </a>
- </li>
-
+ </h3>
+ <ul className="menu">
+ {rule.langName && (
+ <li>
+ <ButtonPlain
+ data-test="coding-rules__similar-language"
+ aria-label={translateWithParameters(
+ 'coding_rules.filter_by_language',
+ rule.langName
+ )}
+ onClick={this.handleLanguageClick}
+ >
+ {rule.langName}
+ </ButtonPlain>
+ </li>
+ )}
<li>
- <a
- className="display-flex-center"
+ <ButtonPlain
+ aria-label={translateWithParameters(
+ 'coding_rules.filter_by_type',
+ translate('issue.type', rule.type)
+ )}
data-test="coding-rules__similar-type"
- href="#"
onClick={this.handleTypeClick}
>
<IssueTypeIcon query={rule.type} />
<span className="little-spacer-left">{translate('issue.type', rule.type)}</span>
- </a>
+ </ButtonPlain>
</li>
{severity && (
<li>
- <a
+ <ButtonPlain
data-test="coding-rules__similar-severity"
- href="#"
+ aria-label={translateWithParameters(
+ 'coding_rules.filter_by_severity',
+ severity
+ )}
onClick={this.handleSeverityClick}
>
- <SeverityHelper className="display-flex-center" severity={rule.severity} />
- </a>
+ <SeverityHelper className="display-flex-center" severity={severity} />
+ </ButtonPlain>
</li>
)}
- {allTags.length > 0 && <li className="divider" />}
- {allTags.map((tag) => (
- <li key={tag}>
- <a
+ {allTags.map((tag, index) => (
+ <li
+ className={classNames('coding-rules-similar-tag', {
+ 'coding-rules-similar-tag-divider': index === 0,
+ })}
+ key={tag}
+ >
+ <ButtonPlain
data-tag={tag}
data-test="coding-rules__similar-tag"
- href="#"
- onClick={this.handleTagClick}
+ aria-label={translateWithParameters('coding_rules.filter_by_tag', tag)}
+ onClick={() => this.handleTagClick(tag)}
>
<TagsIcon className="little-spacer-right text-middle" />
<span className="text-middle">{tag}</span>
- </a>
+ </ButtonPlain>
</li>
))}
</ul>
</>
}
>
- <a
- className="js-rule-filter link-no-underline spacer-left dropdown-toggle"
- href="#"
+ <Button
+ className="js-rule-filter spacer-left"
title={translate('coding_rules.filter_similar_rules')}
>
<FilterIcon />
<DropdownIcon />
- </a>
+ </Button>
</Dropdown>
);
}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/SimilarRulesFilter-test.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/SimilarRulesFilter-test.tsx
index e93d5ac58d0..41629801e7f 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/SimilarRulesFilter-test.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/SimilarRulesFilter-test.tsx
@@ -62,6 +62,6 @@ function mountRenderAction(actionName: string, props: Partial<SimilarRulesFilter
<SimilarRulesFilter onFilterChange={jest.fn()} rule={mockRule()} {...props} />
);
return mount(wrapper.find('Dropdown').prop<React.ReactElement>('overlay'))
- .find(`a[data-test="coding-rules__similar-${actionName}"]`)
+ .find(`button[data-test="coding-rules__similar-${actionName}"]`)
.first();
}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/SimilarRulesFilter-test.tsx.snap b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/SimilarRulesFilter-test.tsx.snap
index 2585ebc6e1d..63f445a90aa 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/SimilarRulesFilter-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/SimilarRulesFilter-test.tsx.snap
@@ -5,30 +5,27 @@ exports[`should render correctly 1`] = `
className="display-inline-block"
overlay={
<React.Fragment>
- <h2
- className="menu-header"
- id="filter-similar-rules"
+ <h3
+ className="coding-rules-filter-title"
>
coding_rules.filter_similar_rules
- </h2>
+ </h3>
<ul
- aria-labelledby="filter-similar-rules"
className="menu"
>
<li>
- <a
+ <ButtonPlain
+ aria-label="coding_rules.filter_by_language.JavaScript"
data-test="coding-rules__similar-language"
- href="#"
onClick={[Function]}
>
JavaScript
- </a>
+ </ButtonPlain>
</li>
<li>
- <a
- className="display-flex-center"
+ <ButtonPlain
+ aria-label="coding_rules.filter_by_type.issue.type.CODE_SMELL"
data-test="coding-rules__similar-type"
- href="#"
onClick={[Function]}
>
<IssueTypeIcon
@@ -39,28 +36,27 @@ exports[`should render correctly 1`] = `
>
issue.type.CODE_SMELL
</span>
- </a>
+ </ButtonPlain>
</li>
<li>
- <a
+ <ButtonPlain
+ aria-label="coding_rules.filter_by_severity.MAJOR"
data-test="coding-rules__similar-severity"
- href="#"
onClick={[Function]}
>
<SeverityHelper
className="display-flex-center"
severity="MAJOR"
/>
- </a>
+ </ButtonPlain>
</li>
<li
- className="divider"
- />
- <li>
- <a
+ className="coding-rules-similar-tag coding-rules-similar-tag-divider"
+ >
+ <ButtonPlain
+ aria-label="coding_rules.filter_by_tag.x"
data-tag="x"
data-test="coding-rules__similar-tag"
- href="#"
onClick={[Function]}
>
<TagsIcon
@@ -71,13 +67,15 @@ exports[`should render correctly 1`] = `
>
x
</span>
- </a>
+ </ButtonPlain>
</li>
- <li>
- <a
+ <li
+ className="coding-rules-similar-tag"
+ >
+ <ButtonPlain
+ aria-label="coding_rules.filter_by_tag.a"
data-tag="a"
data-test="coding-rules__similar-tag"
- href="#"
onClick={[Function]}
>
<TagsIcon
@@ -88,13 +86,15 @@ exports[`should render correctly 1`] = `
>
a
</span>
- </a>
+ </ButtonPlain>
</li>
- <li>
- <a
+ <li
+ className="coding-rules-similar-tag"
+ >
+ <ButtonPlain
+ aria-label="coding_rules.filter_by_tag.b"
data-tag="b"
data-test="coding-rules__similar-tag"
- href="#"
onClick={[Function]}
>
<TagsIcon
@@ -105,19 +105,18 @@ exports[`should render correctly 1`] = `
>
b
</span>
- </a>
+ </ButtonPlain>
</li>
</ul>
</React.Fragment>
}
>
- <a
- className="js-rule-filter link-no-underline spacer-left dropdown-toggle"
- href="#"
+ <Button
+ className="js-rule-filter spacer-left"
title="coding_rules.filter_similar_rules"
>
<FilterIcon />
<DropdownIcon />
- </a>
+ </Button>
</Dropdown>
`;
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/styles.css b/server/sonar-web/src/main/js/apps/coding-rules/styles.css
index 969fcb856de..f7cab25e4cb 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/styles.css
+++ b/server/sonar-web/src/main/js/apps/coding-rules/styles.css
@@ -17,6 +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.
*/
+
.coding-rules-extended-view .coding-rules-list {
display: none;
}
@@ -25,6 +26,19 @@
display: block;
}
+.coding-rules-similar-tag-divider {
+ margin-top: 6px;
+ border-top: 1px solid var(--barBorderColor);
+}
+
+.coding-rules-filter-title {
+ padding: var(--gridSize);
+ font-size: 12px;
+ color: var(--neutral600);
+ white-space: nowrap;
+ line-height: unset;
+}
+
/*
* Detail
*/
@@ -234,7 +248,7 @@
}
.coding-rule-table td {
- vertical-align: top;
+ vertical-align: middle;
}
.coding-rule-table + .coding-rule-table {
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 74aa32dccf8..b4f051af2a0 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -1958,6 +1958,10 @@ coding_rules.type.tooltip.VULNERABILITY=Vulnerability Detection Rule
coding_rules.type.tooltip.SECURITY_HOTSPOT=Security Hotspot Detection Rule
coding_rules.update_custom_rule=Update Custom Rule
coding_rules.filter_similar_rules=Filter Similar Rules
+coding_rules.filter_by_language=Filter by {0} language
+coding_rules.filter_by_type=Filter by {0} type
+coding_rules.filter_by_severity=Filter by {0} severity
+coding_rules.filter_by_tag=Filter by {0} tag
coding_rules.filters.activation=Activation
coding_rules.filters.activation.active=Active