import * as React from 'react';
import * as classNames from 'classnames';
import { Link } from 'react-router';
-import { translate } from '../../../helpers/l10n';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
import { SecurityHotspot, Component, BranchLike, IssueType } from '../../../app/types';
import Rating from '../../../components/ui/Rating';
-import { getComponentIssuesUrl } from '../../../helpers/urls';
+import { getComponentIssuesUrl, getRulesUrl } from '../../../helpers/urls';
import { getBranchLikeQuery } from '../../../helpers/branches';
import HelpTooltip from '../../../components/controls/HelpTooltip';
import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon';
import DetachIcon from '../../../components/icons-components/DetachIcon';
import Tooltip from '../../../components/controls/Tooltip';
import { getRatingTooltip } from '../../../helpers/measures';
+import PlusCircleIcon from '../../../components/icons-components/PlusCircleIcon';
+import { isSonarCloud } from '../../../helpers/system';
+import * as theme from '../../../app/theme';
interface Props {
branchLike?: BranchLike;
);
};
- getName(finding: SecurityHotspot, type: 'owaspTop10' | 'sansTop25' | 'cwe') {
+ getName(
+ finding: SecurityHotspot,
+ type: 'owaspTop10' | 'sansTop25' | 'cwe',
+ activeRules: number,
+ totalRules: number
+ ) {
const category = finding.category || finding.cwe || 'unknown';
const renderers = {
owaspTop10: renderOwaspTop10Category,
overlay={this.renderOverlay(this.state.standards[type][category].description)}
/>
)}
+ {activeRules === 0 &&
+ totalRules > 0 && (
+ <HelpTooltip className="spacer-left" overlay={this.renderMoreRulesOverlay(totalRules)}>
+ <PlusCircleIcon className="vertical-middle" fill={theme.blue} size={12} />
+ </HelpTooltip>
+ )}
</>
);
}
+ renderMoreRulesOverlay = (totalRules: number) => {
+ const languages = this.props.component.qualityProfiles
+ ? this.props.component.qualityProfiles.map(qp => qp.language).join(',')
+ : '';
+ return (
+ <>
+ <p>{translate('security_reports.activate_rules')}</p>
+ <hr className="spacer-top spacer-bottom" />
+ <Link
+ className="spacer-left link-no-underline"
+ to={getRulesUrl(
+ { languages, types: `${IssueType.Hotspot},${IssueType.Vulnerability}` },
+ isSonarCloud() ? this.props.component.organization : undefined
+ )}>
+ {translateWithParameters('security_reports.activate_rules.link', totalRules)}
+ </Link>
+ </>
+ );
+ };
+
renderOverlay = (description: string | undefined) => {
return (
<>
<React.Fragment key={finding.category || finding.cwe}>
<tr>
<td className={classNames({ 'cwe-title-cell': isCWE })}>
- {this.getName(finding, isCWE ? 'cwe' : type)}
+ {this.getName(finding, isCWE ? 'cwe' : type, finding.activeRules, finding.totalRules)}
</td>
<td className="text-right">
{!hasActiveRules && '-'}
>
<React.Fragment>
A3
+ <HelpTooltip
+ className="spacer-left"
+ overlay={
+ <React.Fragment>
+ <p>
+ security_reports.activate_rules
+ </p>
+ <hr
+ className="spacer-top spacer-bottom"
+ />
+ <Link
+ className="spacer-left link-no-underline"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/coding_rules",
+ "query": Object {
+ "languages": "",
+ "types": "SECURITY_HOTSPOT,VULNERABILITY",
+ },
+ }
+ }
+ >
+ security_reports.activate_rules.link.1
+ </Link>
+ </React.Fragment>
+ }
+ >
+ <PlusCircleIcon
+ className="vertical-middle"
+ fill="#4b9fd5"
+ size={12}
+ />
+ </HelpTooltip>
</React.Fragment>
</td>
<td
>
<React.Fragment>
A3
+ <HelpTooltip
+ className="spacer-left"
+ overlay={
+ <React.Fragment>
+ <p>
+ security_reports.activate_rules
+ </p>
+ <hr
+ className="spacer-top spacer-bottom"
+ />
+ <Link
+ className="spacer-left link-no-underline"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/coding_rules",
+ "query": Object {
+ "languages": "",
+ "types": "SECURITY_HOTSPOT,VULNERABILITY",
+ },
+ }
+ }
+ >
+ security_reports.activate_rules.link.1
+ </Link>
+ </React.Fragment>
+ }
+ >
+ <PlusCircleIcon
+ className="vertical-middle"
+ fill="#4b9fd5"
+ size={12}
+ />
+ </HelpTooltip>
</React.Fragment>
</td>
<td