Co-authored-by: Siegfried Ehret <siegfried.ehret@sonarsource.com> Co-authored-by: Wouter Admiraal <wouter.admiraal@sonarsource.com>tags/8.7.0.41497
@@ -107,6 +107,7 @@ module.exports = { | |||
// badge | |||
badgeBlueBackground: '#2E7CB5', | |||
badgeBlueColor: '#FFFFFF', | |||
badgeRedBackgroundOnIssue: '#EEC8C8', | |||
// alm | |||
azure: '#0078d7', |
@@ -240,3 +240,7 @@ | |||
max-height: 120px; | |||
overflow: auto; | |||
} | |||
.issue .badge-error { | |||
background-color: var(--badgeRedBackgroundOnIssue); | |||
} |
@@ -21,6 +21,8 @@ import * as React from 'react'; | |||
import { ButtonLink } from 'sonar-ui-common/components/controls/buttons'; | |||
import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; | |||
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; | |||
import { RuleStatus } from '../../../types/rules'; | |||
import DocumentationTooltip from '../../common/DocumentationTooltip'; | |||
import { WorkspaceContextShape } from '../../workspace/context'; | |||
export interface IssueMessageProps { | |||
@@ -31,10 +33,19 @@ export interface IssueMessageProps { | |||
onOpenRule: WorkspaceContextShape['openRule']; | |||
organization: string; | |||
ruleKey: string; | |||
ruleStatus?: RuleStatus; | |||
} | |||
export default function IssueMessage(props: IssueMessageProps) { | |||
const { engine, engineName, manualVulnerability, message, organization, ruleKey } = props; | |||
const { | |||
engine, | |||
engineName, | |||
manualVulnerability, | |||
message, | |||
organization, | |||
ruleKey, | |||
ruleStatus | |||
} = props; | |||
const ruleEngine = engineName ? engineName : engine; | |||
return ( | |||
@@ -47,6 +58,22 @@ export default function IssueMessage(props: IssueMessageProps) { | |||
{translate('issue.why_this_issue')} | |||
</ButtonLink> | |||
{ruleStatus && (ruleStatus === RuleStatus.Deprecated || ruleStatus === RuleStatus.Removed) && ( | |||
<DocumentationTooltip | |||
className="spacer-left" | |||
content={translate('rules.status', ruleStatus, 'help')} | |||
links={[ | |||
{ | |||
href: '/documentation/user-guide/rules/', | |||
label: translateWithParameters('see_x', translate('rules')) | |||
} | |||
]}> | |||
<span className="spacer-right badge badge-error"> | |||
{translate('rules.status', ruleStatus)} | |||
</span> | |||
</DocumentationTooltip> | |||
)} | |||
{ruleEngine && ( | |||
<Tooltip overlay={translateWithParameters('issue.from_external_rule_engine', ruleEngine)}> | |||
<div className="badge spacer-right text-baseline">{ruleEngine}</div> |
@@ -26,6 +26,7 @@ import { formatMeasure } from 'sonar-ui-common/helpers/measures'; | |||
import { getBranchLikeQuery } from '../../../helpers/branch-like'; | |||
import { getComponentIssuesUrl } from '../../../helpers/urls'; | |||
import { BranchLike } from '../../../types/branch-like'; | |||
import { RuleStatus } from '../../../types/rules'; | |||
import LocationIndex from '../../common/LocationIndex'; | |||
import { WorkspaceContext } from '../../workspace/context'; | |||
import IssueChangelog from './IssueChangelog'; | |||
@@ -85,6 +86,7 @@ export default function IssueTitleBar(props: IssueTitleBarProps) { | |||
onOpenRule={openRule} | |||
organization={issue.organization} | |||
ruleKey={issue.rule} | |||
ruleStatus={issue.ruleStatus as RuleStatus | undefined} | |||
/> | |||
)} | |||
</WorkspaceContext.Consumer> |
@@ -22,6 +22,7 @@ import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { ButtonLink } from 'sonar-ui-common/components/controls/buttons'; | |||
import { click } from 'sonar-ui-common/helpers/testUtils'; | |||
import { RuleStatus } from '../../../../types/rules'; | |||
import IssueMessage, { IssueMessageProps } from '../IssueMessage'; | |||
it('should render correctly', () => { | |||
@@ -29,6 +30,10 @@ it('should render correctly', () => { | |||
expect(shallowRender({ engine: 'js' })).toMatchSnapshot('with engine info'); | |||
expect(shallowRender({ engineName: 'JS' })).toMatchSnapshot('with engine name'); | |||
expect(shallowRender({ manualVulnerability: true })).toMatchSnapshot('is manual vulnerability'); | |||
expect(shallowRender({ ruleStatus: RuleStatus.Deprecated })).toMatchSnapshot( | |||
'is deprecated rule' | |||
); | |||
expect(shallowRender({ ruleStatus: RuleStatus.Removed })).toMatchSnapshot('is removed rule'); | |||
}); | |||
it('should handle click correctly', () => { |
@@ -19,6 +19,43 @@ exports[`should render correctly: default 1`] = ` | |||
</div> | |||
`; | |||
exports[`should render correctly: is deprecated rule 1`] = ` | |||
<div | |||
className="issue-message break-word" | |||
> | |||
<span | |||
className="spacer-right" | |||
> | |||
Reduce the number of conditional operators (4) used in the expression | |||
</span> | |||
<ButtonLink | |||
aria-label="issue.why_this_issue.long" | |||
className="issue-see-rule spacer-right text-baseline" | |||
onClick={[Function]} | |||
> | |||
issue.why_this_issue | |||
</ButtonLink> | |||
<DocumentationTooltip | |||
className="spacer-left" | |||
content="rules.status.DEPRECATED.help" | |||
links={ | |||
Array [ | |||
Object { | |||
"href": "/documentation/user-guide/rules/", | |||
"label": "see_x.rules", | |||
}, | |||
] | |||
} | |||
> | |||
<span | |||
className="spacer-right badge badge-error" | |||
> | |||
rules.status.DEPRECATED | |||
</span> | |||
</DocumentationTooltip> | |||
</div> | |||
`; | |||
exports[`should render correctly: is manual vulnerability 1`] = ` | |||
<div | |||
className="issue-message break-word" | |||
@@ -47,6 +84,43 @@ exports[`should render correctly: is manual vulnerability 1`] = ` | |||
</div> | |||
`; | |||
exports[`should render correctly: is removed rule 1`] = ` | |||
<div | |||
className="issue-message break-word" | |||
> | |||
<span | |||
className="spacer-right" | |||
> | |||
Reduce the number of conditional operators (4) used in the expression | |||
</span> | |||
<ButtonLink | |||
aria-label="issue.why_this_issue.long" | |||
className="issue-see-rule spacer-right text-baseline" | |||
onClick={[Function]} | |||
> | |||
issue.why_this_issue | |||
</ButtonLink> | |||
<DocumentationTooltip | |||
className="spacer-left" | |||
content="rules.status.REMOVED.help" | |||
links={ | |||
Array [ | |||
Object { | |||
"href": "/documentation/user-guide/rules/", | |||
"label": "see_x.rules", | |||
}, | |||
] | |||
} | |||
> | |||
<span | |||
className="spacer-right badge badge-error" | |||
> | |||
rules.status.REMOVED | |||
</span> | |||
</DocumentationTooltip> | |||
</div> | |||
`; | |||
exports[`should render correctly: with engine info 1`] = ` | |||
<div | |||
className="issue-message break-word" |
@@ -0,0 +1,26 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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. | |||
*/ | |||
export enum RuleStatus { | |||
Ready = 'READY', | |||
Beta = 'BETA', | |||
Deprecated = 'DEPRECATED', | |||
Removed = 'REMOVED' | |||
} |
@@ -352,6 +352,7 @@ declare namespace T { | |||
resolution?: string; | |||
rule: string; | |||
ruleName: string; | |||
ruleStatus?: string; | |||
secondaryLocations: FlowLocation[]; | |||
severity: string; | |||
status: string; |
@@ -176,6 +176,7 @@ save=Save | |||
search_results=Search results | |||
search_verb=Search | |||
see_all=See all | |||
see_x=See {0} | |||
select_verb=Select | |||
selected=Selected | |||
set=Set | |||
@@ -1598,9 +1599,11 @@ rules.status.beta=Beta | |||
rules.status.BETA=Beta | |||
rules.status.deprecated=Deprecated | |||
rules.status.DEPRECATED=Deprecated | |||
rules.status.DEPRECATED.help=The rule that generated this issue has been deprecated and will be removed. Once the rule is removed, this issue will no longer appear. | |||
rules.status.ready=Ready | |||
rules.status.READY=Ready | |||
rules.status.REMOVED=Removed | |||
rules.status.REMOVED.help=The rule that generated this issue has been removed. Starting on the next analysis, this issue will no longer appear. | |||
#------------------------------------------------------------------------------ |