diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2019-05-27 10:41:30 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-05-29 20:21:14 +0200 |
commit | 18f20eed6127994e54d2fcc7f9772fdcafcfd25d (patch) | |
tree | 120c3377e1cb4b7e879022b40a4e11c8c601dc06 /server | |
parent | 8bb9de894171df87587f76d3b6829514f79ffff1 (diff) | |
download | sonarqube-18f20eed6127994e54d2fcc7f9772fdcafcfd25d.tar.gz sonarqube-18f20eed6127994e54d2fcc7f9772fdcafcfd25d.zip |
SONAR-12114 Add Links in codeviewer header
Diffstat (limited to 'server')
2 files changed, 118 insertions, 45 deletions
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx index c9f23440479..9a8a57bf77d 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx @@ -21,19 +21,25 @@ import { stringify } from 'querystring'; import * as React from 'react'; import { Link } from 'react-router'; import MeasuresOverlay from './components/MeasuresOverlay'; -import QualifierIcon from '../icons-components/QualifierIcon'; import Dropdown from '../controls/Dropdown'; import Favorite from '../controls/Favorite'; import ListIcon from '../icons-components/ListIcon'; +import QualifierIcon from '../icons-components/QualifierIcon'; import { ButtonIcon } from '../ui/buttons'; import { PopupPlacement } from '../ui/popups'; import { WorkspaceContextShape } from '../workspace/context'; -import { getPathUrlAsString, getBranchLikeUrl, getBaseUrl, getCodeUrl } from '../../helpers/urls'; -import { collapsedDirFromPath, fileFromPath } from '../../helpers/path'; -import { translate } from '../../helpers/l10n'; import { getBranchLikeQuery, isMainBranch } from '../../helpers/branches'; +import { translate } from '../../helpers/l10n'; import { formatMeasure } from '../../helpers/measures'; +import { collapsedDirFromPath, fileFromPath } from '../../helpers/path'; import { omitNil } from '../../helpers/request'; +import { + getBranchLikeUrl, + getBaseUrl, + getCodeUrl, + getComponentIssuesUrl, + getPathUrlAsString +} from '../../helpers/urls'; interface Props { branchLike: T.BranchLike | undefined; @@ -65,8 +71,42 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State this.props.openComponent({ branchLike: this.props.branchLike, key }); }; + renderIssueMeasures = () => { + const { branchLike, issues, sourceViewerFile } = this.props; + if (issues && issues.length > 0) { + return ( + <> + <div className="source-viewer-header-measure-separator" /> + + {['BUG', 'VULNERABILITY', 'CODE_SMELL', 'SECURITY_HOTSPOT'].map((type: T.IssueType) => { + const params = { + ...getBranchLikeQuery(branchLike), + fileUuids: sourceViewerFile.uuid, + resolved: 'false', + types: type + }; + + const total = issues.filter(issue => issue.type === type).length; + return ( + <div className="source-viewer-header-measure" key={type}> + <span className="source-viewer-header-measure-label"> + {translate('issue.type', type)} + </span> + <span className="source-viewer-header-measure-value"> + <Link to={getComponentIssuesUrl(sourceViewerFile.project, params)}> + {formatMeasure(total, 'INT')} + </Link> + </span> + </div> + ); + })} + </> + ); + } + }; + render() { - const { issues, showMeasures } = this.props; + const { showMeasures } = this.props; const { key, measures, @@ -77,7 +117,7 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State subProject, subProjectName } = this.props.sourceViewerFile; - const isUnitTest = q === 'UTS'; + const unitTestsOrLines = q === 'UTS' ? 'tests' : 'lines'; const workspace = false; const rawSourcesLink = getBaseUrl() + @@ -129,24 +169,13 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State {showMeasures && ( <div className="display-flex-center"> - {isUnitTest && ( + {measures[unitTestsOrLines] && ( <div className="source-viewer-header-measure"> <span className="source-viewer-header-measure-label"> - {translate('metric.tests.name')} + {translate(`metric.${unitTestsOrLines}.name`)} </span> <span className="source-viewer-header-measure-value"> - {formatMeasure(measures.tests, 'SHORT_INT')} - </span> - </div> - )} - - {!isUnitTest && ( - <div className="source-viewer-header-measure"> - <span className="source-viewer-header-measure-label"> - {translate('metric.lines.name')} - </span> - <span className="source-viewer-header-measure-value"> - {formatMeasure(measures.lines, 'SHORT_INT')} + {formatMeasure(measures[unitTestsOrLines], 'SHORT_INT')} </span> </div> )} @@ -173,27 +202,7 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State </div> )} - {issues && issues.length > 0 && ( - <> - <div className="source-viewer-header-measure-separator" /> - - {['BUG', 'VULNERABILITY', 'CODE_SMELL', 'SECURITY_HOTSPOT'].map( - (type: T.IssueType) => { - const total = issues.filter(issue => issue.type === type).length; - return ( - <div className="source-viewer-header-measure" key={type}> - <span className="source-viewer-header-measure-label"> - {translate('issue.type', type)} - </span> - <span className="source-viewer-header-measure-value"> - {formatMeasure(total, 'INT')} - </span> - </div> - ); - } - )} - </> - )} + {this.renderIssueMeasures()} </div> )} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeader-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeader-test.tsx.snap index f5b7d5831f9..73167d83070 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeader-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeader-test.tsx.snap @@ -346,7 +346,23 @@ exports[`should render correctly if issue details are passed 1`] = ` <span className="source-viewer-header-measure-value" > - 0 + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "fileUuids": "foo-bar", + "id": "my-project", + "resolved": "false", + "types": "BUG", + }, + } + } + > + 0 + </Link> </span> </div> <div @@ -361,7 +377,23 @@ exports[`should render correctly if issue details are passed 1`] = ` <span className="source-viewer-header-measure-value" > - 2 + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "fileUuids": "foo-bar", + "id": "my-project", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + 2 + </Link> </span> </div> <div @@ -376,7 +408,23 @@ exports[`should render correctly if issue details are passed 1`] = ` <span className="source-viewer-header-measure-value" > - 1 + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "fileUuids": "foo-bar", + "id": "my-project", + "resolved": "false", + "types": "CODE_SMELL", + }, + } + } + > + 1 + </Link> </span> </div> <div @@ -391,7 +439,23 @@ exports[`should render correctly if issue details are passed 1`] = ` <span className="source-viewer-header-measure-value" > - 2 + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "fileUuids": "foo-bar", + "id": "my-project", + "resolved": "false", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 2 + </Link> </span> </div> </div> |