diff options
author | Kevin Silva <kevin.silva@sonarsource.com> | 2023-01-10 14:41:42 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-01-16 20:03:43 +0000 |
commit | 4b10923c40d03bf25fff9cb1bcd92ae15db567ce (patch) | |
tree | 32d430b5cc32adcd2a57a2ce88c4aec439bacd39 | |
parent | 3940b153fe70a090dd1bc6c44ab3c43e2727cbb1 (diff) | |
download | sonarqube-4b10923c40d03bf25fff9cb1bcd92ae15db567ce.tar.gz sonarqube-4b10923c40d03bf25fff9cb1bcd92ae15db567ce.zip |
SONAR-17845 [1096026, 1099611] Multiple links have the same programmatic link text but different destinations
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 |