cursor: pointer;
}
-.location-index[tabindex]:hover {
+.location-index[tabindex]:hover,
+a:hover > .location-index {
background-color: #bc5e5e;
}
outline: none;
}
-.source-line-code .location-index {
+.source-line-code-inner .location-index {
line-height: 16px;
margin: 1px;
margin-left: 4px;
margin-right: 4px;
}
-.source-line-code .location-index + .location-index {
+.source-line-code-inner .location-index + .location-index {
margin-left: 0;
}
\ No newline at end of file
import IssueChangelog from './IssueChangelog';
import IssueMessage from './IssueMessage';
import SimilarIssuesFilter from './SimilarIssuesFilter';
+import LocationIndex from '../../common/LocationIndex';
+import Tooltip from '../../controls/Tooltip';
import { getSingleIssueUrl } from '../../../helpers/urls';
-import { translate } from '../../../helpers/l10n';
+import { formatMeasure } from '../../../helpers/measures';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
import type { Issue } from '../types';
type Props = {|
const { issue } = props;
const hasSimilarIssuesFilter = props.onFilter != null;
+ const locationsCount =
+ issue.secondaryLocations.length +
+ issue.flows.reduce((sum, locations) => sum + locations.length, 0);
+
+ const locationsBadge = (
+ <Tooltip
+ overlay={translateWithParameters(
+ 'issue.this_issue_involves_x_code_locations',
+ formatMeasure(locationsCount)
+ )}
+ placement="left">
+ <LocationIndex>{locationsCount}</LocationIndex>
+ </Tooltip>
+ );
+
+ // dirty trick :(
+ const onIssuesPage = document.getElementById('issues-page') != null;
+
return (
<table className="issue-table">
<tbody>
L{issue.line}
</span>
</li>}
+ {locationsCount > 0 &&
+ <li className="issue-meta">
+ {onIssuesPage
+ ? locationsBadge
+ : <Link onClick={stopPropagation} to={getSingleIssueUrl(issue.key)}>
+ {locationsBadge}
+ </Link>}
+ </li>}
<li className="issue-meta">
<Link
className="js-issue-permalink icon-link"
organization: 'myorg',
key: 'AVsae-CQS-9G3txfbFN2',
rule: 'javascript:S1067',
- message: 'Reduce the number of conditional operators (4) used in the expression'
+ message: 'Reduce the number of conditional operators (4) used in the expression',
+ flows: [],
+ secondaryLocations: []
};
it('should render the titlebar correctly', () => {
);
expect(element).toMatchSnapshot();
});
+
+it('should count all code locations', () => {
+ const issueWithLocations = {
+ ...issue,
+ flows: [[{}, {}, {}], [{}, {}]],
+ secondaryLocations: [{}, {}]
+ };
+ const element = shallow(<IssueTitleBar issue={issueWithLocations} />);
+ expect(element.find('LocationIndex').children().text()).toBe('7');
+});
issue={
Object {
"creationDate": "2017-03-01T09:36:01+0100",
+ "flows": Array [],
"key": "AVsae-CQS-9G3txfbFN2",
"line": 26,
"message": "Reduce the number of conditional operators (4) used in the expression",
"organization": "myorg",
"rule": "javascript:S1067",
+ "secondaryLocations": Array [],
}
}
onFail={[Function]}
issue={
Object {
"creationDate": "2017-03-01T09:36:01+0100",
+ "flows": Array [],
"key": "AVsae-CQS-9G3txfbFN2",
"line": 26,
"message": "Reduce the number of conditional operators (4) used in the expression",
"organization": "myorg",
"rule": "javascript:S1067",
+ "secondaryLocations": Array [],
}
}
onFail={[Function]}
issue={
Object {
"creationDate": "2017-03-01T09:36:01+0100",
+ "flows": Array [],
"key": "AVsae-CQS-9G3txfbFN2",
"line": 26,
"message": "Reduce the number of conditional operators (4) used in the expression",
"organization": "myorg",
"rule": "javascript:S1067",
+ "secondaryLocations": Array [],
}
}
onFail={[Function]}
left: 50%;
margin: -8px 0 0 -8px;
}
+
+.issue:not(.selected) .location-index {
+ background-color: #ccc;
+}
\ No newline at end of file