]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12367 Show total issues in codeviewer header
authorJeremy Davis <jeremy.davis@sonarsource.com>
Wed, 13 Nov 2019 09:06:17 +0000 (18:06 +0900)
committerSonarTech <sonartech@sonarsource.com>
Wed, 4 Dec 2019 19:46:09 +0000 (20:46 +0100)
server/sonar-web/src/main/js/apps/code/components/App.tsx
server/sonar-web/src/main/js/apps/code/components/SourceViewerWrapper.tsx
server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx
server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx
server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerHeader-test.tsx

index ce34389013df587cced53e4c543c23feb349c890..7135d3fe6a08d35e1fbe1e54b4657d8e2f1d710d 100644 (file)
@@ -327,6 +327,7 @@ export class App extends React.PureComponent<Props, State> {
               <SourceViewerWrapper
                 branchLike={branchLike}
                 component={sourceViewer.key}
+                componentMeasures={sourceViewer.measures}
                 isFile={true}
                 location={location}
                 onGoToParent={this.handleGoToParent}
index 438a17f0178a0453de56f5438895380249d58415..f9882605bbc37788d5613f77b0938090844edbe8 100644 (file)
@@ -26,6 +26,7 @@ import SourceViewer from '../../../components/SourceViewer/SourceViewer';
 interface Props {
   branchLike?: T.BranchLike;
   component: string;
+  componentMeasures: T.Measure[] | undefined;
   location: Pick<Location, 'query'>;
   onIssueChange?: (issue: T.Issue) => void;
 }
@@ -44,7 +45,7 @@ export class SourceViewerWrapper extends React.PureComponent<Props> {
   };
 
   render() {
-    const { branchLike, component, location } = this.props;
+    const { branchLike, component, componentMeasures, location } = this.props;
     const { line } = location.query;
     const finalLine = line ? Number(line) : undefined;
 
@@ -53,6 +54,7 @@ export class SourceViewerWrapper extends React.PureComponent<Props> {
         aroundLine={finalLine}
         branchLike={branchLike}
         component={component}
+        componentMeasures={componentMeasures}
         highlightedLine={finalLine}
         onIssueChange={this.props.onIssueChange}
         onLoaded={this.scrollToLine}
index 22b82d5f11aa8285c7f2407200e6a157239d4aaf..e66edd4fde0113b67c8df0bc4d9c8e735079af22 100644 (file)
@@ -56,6 +56,7 @@ export interface Props {
   aroundLine?: number;
   branchLike: T.BranchLike | undefined;
   component: string;
+  componentMeasures?: T.Measure[];
   displayAllIssues?: boolean;
   displayIssueLocationsCount?: boolean;
   displayIssueLocationsLink?: boolean;
@@ -664,7 +665,7 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
         {({ openComponent }) => (
           <SourceViewerHeader
             branchLike={this.props.branchLike}
-            issues={this.state.issues}
+            componentMeasures={this.props.componentMeasures}
             openComponent={openComponent}
             showMeasures={this.props.showMeasures}
             sourceViewerFile={sourceViewerFile}
index 18ec3d1a0912e45a698eedb631cef49fc8eaab3e..c54a71591b5bf50842c441f2fef7fcbbabc8520e 100644 (file)
@@ -39,7 +39,7 @@ import MeasuresOverlay from './components/MeasuresOverlay';
 
 interface Props {
   branchLike: T.BranchLike | undefined;
-  issues?: T.Issue[];
+  componentMeasures?: T.Measure[];
   openComponent: WorkspaceContextShape['openComponent'];
   showMeasures?: boolean;
   sourceViewerFile: T.SourceViewerFile;
@@ -49,6 +49,13 @@ interface State {
   measuresOverlay: boolean;
 }
 
+const METRIC_KEY_FOR_ISSUE_TYPE: { [type in T.IssueType]: string } = {
+  BUG: 'bugs',
+  VULNERABILITY: 'vulnerabilities',
+  CODE_SMELL: 'code_smells',
+  SECURITY_HOTSPOT: 'security_hotspots'
+};
+
 export default class SourceViewerHeader extends React.PureComponent<Props, State> {
   state: State = { measuresOverlay: false };
 
@@ -68,10 +75,10 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State
   };
 
   renderIssueMeasures = () => {
-    const { branchLike, issues, sourceViewerFile } = this.props;
+    const { branchLike, componentMeasures, sourceViewerFile } = this.props;
     return (
-      issues &&
-      issues.length > 0 && (
+      componentMeasures &&
+      componentMeasures.length > 0 && (
         <>
           <div className="source-viewer-header-measure-separator" />
 
@@ -83,7 +90,9 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State
               types: type
             };
 
-            const total = issues.filter(issue => issue.type === type).length;
+            const measure = componentMeasures.find(
+              m => m.metric === METRIC_KEY_FOR_ISSUE_TYPE[type]
+            );
             return (
               <div className="source-viewer-header-measure" key={type}>
                 <span className="source-viewer-header-measure-label">
@@ -91,7 +100,7 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State
                 </span>
                 <span className="source-viewer-header-measure-value">
                   <Link to={getComponentIssuesUrl(sourceViewerFile.project, params)}>
-                    {formatMeasure(total, 'INT')}
+                    {formatMeasure((measure && measure.value) || 0, 'INT')}
                   </Link>
                 </span>
               </div>
index 3a78dea570a234bac8749f20010de6c92de4998c..385046e2078bd7dff51074194fa92d6060c20eeb 100644 (file)
@@ -19,7 +19,7 @@
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
-import { mockIssue, mockMainBranch, mockSourceViewerFile } from '../../../helpers/testMocks';
+import { mockMainBranch, mockSourceViewerFile } from '../../../helpers/testMocks';
 import SourceViewerHeader from '../SourceViewerHeader';
 
 it('should render correctly for a regular file', () => {
@@ -36,24 +36,23 @@ it('should render correctly for a unit test', () => {
 });
 
 it('should render correctly if issue details are passed', () => {
-  const issues = [
-    mockIssue(false, { type: 'VULNERABILITY' }),
-    mockIssue(false, { type: 'VULNERABILITY' }),
-    mockIssue(false, { type: 'CODE_SMELL' }),
-    mockIssue(false, { type: 'SECURITY_HOTSPOT' }),
-    mockIssue(false, { type: 'SECURITY_HOTSPOT' })
+  const componentMeasures: T.Measure[] = [
+    { metric: 'code_smells', value: '1' },
+    { metric: 'unused_metric_to_be_ignored', value: '42' },
+    { metric: 'security_hotspots', value: '2' },
+    { metric: 'vulnerabilities', value: '2' }
   ];
 
   expect(
     shallowRender({
-      issues,
+      componentMeasures,
       showMeasures: true
     })
   ).toMatchSnapshot();
 
   expect(
     shallowRender({
-      issues,
+      componentMeasures,
       showMeasures: false
     })
       .find('.source-viewer-header-measure')