]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5209 Issues filtering
authorStas Vilchik <vilchiks@gmail.com>
Mon, 19 May 2014 08:59:05 +0000 (10:59 +0200)
committerStas Vilchik <vilchiks@gmail.com>
Mon, 19 May 2014 08:59:12 +0000 (10:59 +0200)
sonar-server/src/main/coffee/component-viewer/header.coffee
sonar-server/src/main/coffee/component-viewer/main.coffee
sonar-server/src/main/coffee/component-viewer/source.coffee
sonar-server/src/main/hbs/component-viewer/header.hbs
sonar-server/src/main/hbs/component-viewer/header/_issues-header.hbs
sonar-server/src/main/js/common/handlebars-extensions.js
sonar-server/src/main/js/issues/extra.js

index 731268a19dcd71b4aac769c0d89b1a3e3ff48240..d8e0e4b5968e5a8f4c934914583851a5991d7bc0 100644 (file)
@@ -27,13 +27,23 @@ define [
       'click .js-toggle-duplications': 'toggleDuplications'
       'click .js-toggle-scm': 'toggleSCM'
 
+      'click .js-filter-current-issue': 'filterByCurrentIssue'
+      'click .js-filter-all-issues': 'filterByAllIssues'
+      'click .js-filter-resolved-issues': 'filterByResolvedIssues'
+      'click .js-filter-unresolved-issues': 'filterByUnresolvedIssues'
+      'click .js-filter-false-positive-issues': 'filterByFalsePositiveIssues'
+      'click .js-filter-blocker-issues': 'filterByBlockerIssues'
+      'click .js-filter-critical-issues': 'filterByCriticalIssues'
+      'click .js-filter-major-issues': 'filterByMajorIssues'
+      'click .js-filter-minor-issues': 'filterByMinorIssues'
+      'click .js-filter-info-issues': 'filterByInfoIssues'
+
       'click .js-filter-lines-to-cover': 'filterByLinesToCover'
       'click .js-filter-covered-lines': 'filterByCoveredLines'
       'click .js-filter-uncovered-lines': 'filterByUncoveredLines'
       'click .js-filter-branches-to-cover': 'filterByBranchesToCover'
       'click .js-filter-covered-branches': 'filterByCoveredBranches'
       'click .js-filter-uncovered-branches': 'filterByUncoveredBranches'
-
       'click .js-filter-lines-to-cover-it': 'filterByLinesToCoverIT'
       'click .js-filter-covered-lines-it': 'filterByCoveredLinesIT'
       'click .js-filter-uncovered-lines-it': 'filterByUncoveredLinesIT'
@@ -90,25 +100,40 @@ define [
     toggleWorkspace: (e) -> @toggleSetting e, @options.main.showWorkspace, @options.main.hideWorkspace
 
 
-    filterByCoverage: (e, method) ->
+    filterLines: (e, method) ->
       @$('.component-viewer-header-expanded-bar-section-list .active').removeClass 'active'
       $(e.currentTarget).addClass 'active'
       _.result @options.main, method
 
 
-    filterByLinesToCover: (e) -> @filterByCoverage e, 'filterByLinesToCover'
-    filterByCoveredLines: (e) -> @filterByCoverage e, 'filterByCoveredLines'
-    filterByUncoveredLines: (e) -> @filterByCoverage e, 'filterByUncoveredLines'
-    filterByBranchesToCover: (e) -> @filterByCoverage e, 'filterByBranchesToCover'
-    filterByCoveredBranches: (e) -> @filterByCoverage e, 'filterByCoveredBranches'
-    filterByUncoveredBranches: (e) -> @filterByCoverage e, 'filterByUncoveredBranches'
-
-    filterByLinesToCoverIT: (e) -> @filterByCoverage e, 'filterByLinesToCoverIT'
-    filterByCoveredLinesIT: (e) -> @filterByCoverage e, 'filterByCoveredLinesIT'
-    filterByUncoveredLinesIT: (e) -> @filterByCoverage e, 'filterByUncoveredLinesIT'
-    filterByBranchesToCoverIT: (e) -> @filterByCoverage e, 'filterByBranchesToCoverIT'
-    filterByCoveredBranchesIT: (e) -> @filterByCoverage e, 'filterByCoveredBranchesIT'
-    filterByUncoveredBranchesIT: (e) -> @filterByCoverage e, 'filterByUncoveredBranchesIT'
+    # Issues
+    filterByCurrentIssue: (e) -> @filterLines e, 'filterByCurrentIssue'
+    filterByAllIssues: (e) -> @filterLines e, 'filterByAllIssues'
+    filterByResolvedIssues: (e) -> @filterLines e, 'filterByResolvedIssues'
+    filterByUnresolvedIssues: (e) -> @filterLines e, 'filterByUnresolvedIssues'
+    filterByFalsePositiveIssues: (e) -> @filterLines e, 'filterByFalsePositiveIssues'
+
+    filterByBlockerIssues: (e) -> @filterLines e, 'filterByBlockerIssues'
+    filterByCriticalIssues: (e) -> @filterLines e, 'filterByCriticalIssues'
+    filterByMajorIssues: (e) -> @filterLines e, 'filterByMajorIssues'
+    filterByMinorIssues: (e) -> @filterLines e, 'filterByMinorIssues'
+    filterByInfoIssues: (e) -> @filterLines e, 'filterByInfoIssues'
+
+
+    # Coverage
+    filterByLinesToCover: (e) -> @filterLines e, 'filterByLinesToCover'
+    filterByCoveredLines: (e) -> @filterLines e, 'filterByCoveredLines'
+    filterByUncoveredLines: (e) -> @filterLines e, 'filterByUncoveredLines'
+    filterByBranchesToCover: (e) -> @filterLines e, 'filterByBranchesToCover'
+    filterByCoveredBranches: (e) -> @filterLines e, 'filterByCoveredBranches'
+    filterByUncoveredBranches: (e) -> @filterLines e, 'filterByUncoveredBranches'
+
+    filterByLinesToCoverIT: (e) -> @filterLines e, 'filterByLinesToCoverIT'
+    filterByCoveredLinesIT: (e) -> @filterLines e, 'filterByCoveredLinesIT'
+    filterByUncoveredLinesIT: (e) -> @filterLines e, 'filterByUncoveredLinesIT'
+    filterByBranchesToCoverIT: (e) -> @filterLines e, 'filterByBranchesToCoverIT'
+    filterByCoveredBranchesIT: (e) -> @filterLines e, 'filterByCoveredBranchesIT'
+    filterByUncoveredBranchesIT: (e) -> @filterLines e, 'filterByUncoveredBranchesIT'
 
 
     serializeData: ->
index 1cdde9a823a73b0c8a5b2f21119051d1007c4cd9..7c65a0088293f33cc0451daa9e30d7c607fd62ea 100644 (file)
@@ -20,6 +20,7 @@ define [
 
   API_COMPONENT = "#{baseUrl}/api/components/app"
   API_SOURCES = "#{baseUrl}/api/sources/show"
+  API_ISSUES = "#{baseUrl}/api/issues/search"
   API_COVERAGE = "#{baseUrl}/api/coverage/show"
   API_SCM = "#{baseUrl}/api/sources/scm"
   API_MEASURES = "#{baseUrl}/api/resources"
@@ -80,6 +81,8 @@ define [
         model: @source
         main: @
 
+      @requestIssuesOnce = false
+
 
     onRender: ->
       if @settings.get 'workspace'
@@ -128,6 +131,12 @@ define [
         @source.set scm: data.scm
 
 
+    requestIssues: (key) ->
+      $.get API_ISSUES, components: key, ps: 10000, (data) =>
+        @requestIssuesOnce = true
+        @source.set issues: data.issues
+
+
     requestCoverage: (key, type = 'UT') ->
       $.get API_COVERAGE, key: key, type: type, (data) =>
         @source.set coverage: data.coverage
@@ -176,11 +185,12 @@ define [
       @render()
 
 
-    showIssues: (issues) ->
+    showIssues: (issue) ->
       @settings.set 'issues', true
-      if _.isArray(issues) && issues.length > 0
-        @source.set 'issues', issues
-        @filterLinesByIssues()
+      if issue?
+        @currentIssue = issue.key
+        @source.set 'issues', [issue]
+        @filterByCurrentIssue()
       else
         @sourceView.render()
 
@@ -222,6 +232,50 @@ define [
       @sourceView.render()
 
 
+    filterByIssues: (predicate, requestIssues = true) ->
+      if requestIssues && !@requestIssuesOnce
+        @requestIssues(@key).done => @_filterByIssues(predicate)
+      else
+        @_filterByIssues(predicate)
+
+
+    _filterByIssues: (predicate) ->
+      issues = @source.get 'issues'
+      @settings.set 'issues', true
+      @sourceView.resetShowBlocks()
+      activeIssues = []
+      issues.forEach (issue) =>
+        if predicate issue
+          line = issue.line || 0
+          @sourceView.addShowBlock line - LINES_AROUND_ISSUE, line + LINES_AROUND_ISSUE
+          activeIssues.push issue
+      @source.set 'activeIssues', activeIssues
+      @sourceView.render()
+
+
+    # Current Issue
+    filterByCurrentIssue: -> @filterByIssues ((issue) => issue.key == @currentIssue), false
+
+    # All Issues
+    filterByAllIssues: -> @filterByIssues -> true
+
+    # Resolved Issues
+    filterByResolvedIssues: -> @filterByIssues (issue) -> !!issue.resolution
+
+    # Unresolved Issues
+    filterByUnresolvedIssues: -> @filterByIssues (issue) -> !issue.resolution
+
+    # False Positive
+    filterByFalsePositiveIssues: -> @filterByIssues (issue) -> issue.resolution == 'FALSE-POSITIVE'
+
+    # Severity
+    filterByBlockerIssues: -> @filterByIssues (issue) -> issue.severity == 'BLOCKER' && !issue.resolution
+    filterByCriticalIssues: -> @filterByIssues (issue) -> issue.severity == 'CRITICAL' && !issue.resolution
+    filterByMajorIssues: -> @filterByIssues (issue) -> issue.severity == 'MAJOR' && !issue.resolution
+    filterByMinorIssues: -> @filterByIssues (issue) -> issue.severity == 'MINOR' && !issue.resolution
+    filterByInfoIssues: -> @filterByIssues (issue) -> issue.severity == 'INFO' && !issue.resolution
+
+
     filterByCoverage: (predicate) ->
       @requestCoverage(@key).done => @_filterByCoverage(predicate)
 
@@ -258,9 +312,6 @@ define [
     filterByUncoveredBranchesIT: -> @filterByCoverageIT (c) -> c[3]? && c[4]? && (c[3] > c[4])
 
 
-
-
-
     addTransition: (key, transition, optionsForCurrent, options) ->
       if optionsForCurrent?
         last = @workspace.at(@workspace.length - 1)
index b5b01020a8bc0c5fdbf22f8c1038b6f383635fe1..fdd1fa9f0570445f8c35769997ea873b42404b9c 100644 (file)
@@ -59,7 +59,7 @@ define [
       @delegateEvents()
       @showSettings = false
       @renderExpandButtons()
-      @renderIssues() if @options.main.settings.get('issues') && @model.has('issues')
+      @renderIssues() if @options.main.settings.get('issues') && @model.has('activeIssues')
 
 
     renderExpandButtons: ->
@@ -81,7 +81,7 @@ define [
 
 
     renderIssues: ->
-      issues = @model.get 'issues'
+      issues = @model.get 'activeIssues'
       issues.forEach (issue) =>
         line = issue.line || 0
         row = @$("[data-line-number=#{line}]")
index b4070fded7829038ddbafb9d4183939d7c44d4fe..c039f3e2a4badb1d665b25b1392bf7188a0cfb67 100644 (file)
 
     <div class="component-viewer-header-measures-scope">
       <a data-scope="issues" class="component-viewer-header-measures-expand">
-        {{#if component.measures.fDebt}}
           <div class="component-viewer-header-measure">
-            <span class="component-viewer-header-measure-value">{{component.measures.fDebt}}</span>
+            <span class="component-viewer-header-measure-value">{{default component.measures.fDebt 0}}</span>
             <span class="component-viewer-header-measure-label">Debt</span>
           </div>
-        {{/if}}
         {{#if component.measures.fIssues}}
           <div class="component-viewer-header-measure">
             <span class="component-viewer-header-measure-value">{{component.measures.fIssues}}</span>
             <span class="component-viewer-header-measure-label">{{t 'metric.violations.name'}}</span>
           </div>
         {{/if}}
-        <div class="component-viewer-header-measure">
-          <div class="component-viewer-header-measure-issues">
-            <div class="component-viewer-header-measure-issue s-blocker"
-                 style="width: {{percent component.measures.fBlockerIssues component.measures.maxIssues}}%;"></div>
-            <div class="component-viewer-header-measure-issue s-critical"
-                 style="width: {{percent component.measures.fCriticalIssues component.measures.maxIssues}}%;"></div>
-            <div class="component-viewer-header-measure-issue s-major"
-                 style="width: {{percent component.measures.fMajorIssues component.measures.maxIssues}}%;"></div>
-            <div class="component-viewer-header-measure-issue s-minor"
-                 style="width: {{percent component.measures.fMinorIssues component.measures.maxIssues}}%;"></div>
-            <div class="component-viewer-header-measure-issue s-info"
-                 style="width: {{percent component.measures.fInfoIssues component.measures.maxIssues}}%;"></div>
+        {{#if component.measures.fIssues}}
+          <div class="component-viewer-header-measure">
+            <div class="component-viewer-header-measure-issues">
+              <div class="component-viewer-header-measure-issue s-blocker"
+                   style="width: {{percent component.measures.fBlockerIssues component.measures.maxIssues}}%;"></div>
+              <div class="component-viewer-header-measure-issue s-critical"
+                   style="width: {{percent component.measures.fCriticalIssues component.measures.maxIssues}}%;"></div>
+              <div class="component-viewer-header-measure-issue s-major"
+                   style="width: {{percent component.measures.fMajorIssues component.measures.maxIssues}}%;"></div>
+              <div class="component-viewer-header-measure-issue s-minor"
+                   style="width: {{percent component.measures.fMinorIssues component.measures.maxIssues}}%;"></div>
+              <div class="component-viewer-header-measure-issue s-info"
+                   style="width: {{percent component.measures.fInfoIssues component.measures.maxIssues}}%;"></div>
+            </div>
           </div>
-        </div>
+        {{/if}}
         <i class="icon-dropdown"></i>
       </a>
       <a data-scope="issues" title="Toggle issues"
index 3298f8bbac03d372a3f8d0fe957ae34ac065e826..8dacac532ffef6d04c279b4a453a898e97364795 100644 (file)
@@ -1,59 +1,70 @@
-<div class="component-viewer-header-expanded-bar-section">
-  <div class="component-viewer-header-expanded-bar-section-title">Severities</div>
-  <ul class="component-viewer-header-expanded-bar-section-list">
-    {{#if component.msr.blocker_violations}}
-      <li><a class="item">
-        <span><i class="icon-severity-blocker"></i> {{t 'severity.BLOCKER'}}</span>
-        <span class="number">{{component.msr.blocker_violations}}</span>
-        <i class="icon-chevron-right"></i>
-      </a></li>
-    {{/if}}
-    {{#if component.msr.critical_violations}}
-      <li><a class="item">
-        <span><i class="icon-severity-critical"></i> {{t 'severity.CRITICAL'}}</span>
-        <span class="number">{{component.msr.critical_violations}}</span>
-        <i class="icon-chevron-right"></i>
-      </a></li>
-    {{/if}}
-    {{#if component.msr.major_violations}}
-      <li><a class="item">
-        <span><i class="icon-severity-major"></i> {{t 'severity.MAJOR'}}</span>
-        <span class="number">{{component.msr.major_violations}}</span>
-        <i class="icon-chevron-right"></i>
-      </a></li>
-    {{/if}}
-    {{#if component.msr.minor_violations}}
-      <li><a class="item">
-        <span><i class="icon-severity-minor"></i> {{t 'severity.MINOR'}}</span>
-        <span class="number">{{component.msr.minor_violations}}</span>
-        <i class="icon-chevron-right"></i>
-      </a></li>
-    {{/if}}
-    {{#if component.msr.info_violations}}
-      <li><a class="item">
-        <span><i class="icon-severity-info"></i> {{t 'severity.INFO'}}</span>
-        <span class="number">{{component.msr.info_violations}}</span>
-        <i class="icon-chevron-right"></i>
-      </a></li>
-    {{/if}}
-  </ul>
-</div>
+{{#if component.measures.fIssues}}
+  <div class="component-viewer-header-expanded-bar-section">
+    <div class="component-viewer-header-expanded-bar-section-title">Severities</div>
+    <ul class="component-viewer-header-expanded-bar-section-list">
+      {{#if component.msr.blocker_violations}}
+        <li><a class="item js-filter-blocker-issues">
+          <span><i class="icon-severity-blocker"></i> {{t 'severity.BLOCKER'}}</span>
+          <span class="number">{{component.msr.blocker_violations}}</span>
+          <i class="icon-chevron-right"></i>
+        </a></li>
+      {{/if}}
+      {{#if component.msr.critical_violations}}
+        <li><a class="item js-filter-critical-issues">
+          <span><i class="icon-severity-critical"></i> {{t 'severity.CRITICAL'}}</span>
+          <span class="number">{{component.msr.critical_violations}}</span>
+          <i class="icon-chevron-right"></i>
+        </a></li>
+      {{/if}}
+      {{#if component.msr.major_violations}}
+        <li><a class="item js-filter-major-issues">
+          <span><i class="icon-severity-major"></i> {{t 'severity.MAJOR'}}</span>
+          <span class="number">{{component.msr.major_violations}}</span>
+          <i class="icon-chevron-right"></i>
+        </a></li>
+      {{/if}}
+      {{#if component.msr.minor_violations}}
+        <li><a class="item js-filter-minor-issues">
+          <span><i class="icon-severity-minor"></i> {{t 'severity.MINOR'}}</span>
+          <span class="number">{{component.msr.minor_violations}}</span>
+          <i class="icon-chevron-right"></i>
+        </a></li>
+      {{/if}}
+      {{#if component.msr.info_violations}}
+        <li><a class="item js-filter-info-issues">
+          <span><i class="icon-severity-info"></i> {{t 'severity.INFO'}}</span>
+          <span class="number">{{component.msr.info_violations}}</span>
+          <i class="icon-chevron-right"></i>
+        </a></li>
+      {{/if}}
+    </ul>
+  </div>
+{{/if}}
 
-<div class="component-viewer-header-expanded-bar-section">
-  <div class="component-viewer-header-expanded-bar-section-title">Rules</div>
-  <ul class="component-viewer-header-expanded-bar-section-list">
-  </ul>
-</div>
+{{#if component.measures.fIssues}}
+  <div class="component-viewer-header-expanded-bar-section">
+    <div class="component-viewer-header-expanded-bar-section-title">Rules</div>
+    <ul class="component-viewer-header-expanded-bar-section-list">
+    </ul>
+  </div>
+{{/if}}
 
 <div class="component-viewer-header-expanded-bar-section">
-  <div class="component-viewer-header-expanded-bar-section-title">&nbsp;</div>
+  <div class="component-viewer-header-expanded-bar-section-title">Issues</div>
   <ul class="component-viewer-header-expanded-bar-section-list">
-    <li><a class="item">
-      <span>Current issue</span>
+    <li><a class="item js-filter-current-issue">
+      <span>Current Issue</span>
       <i class="icon-chevron-right"></i>
     </a></li>
+    {{#if component.measures.fIssues}}
+      <li><a class="item js-filter-unresolved-issues">
+        <span>Unresolved Issues</span>
+        <span class="number">{{component.measures.fIssues}}</span>
+        <i class="icon-chevron-right"></i>
+      </a></li>
+    {{/if}}
     {{#if component.msr.false_positive_issues}}
-      <li><a class="item">
+      <li><a class="item js-filter-false-positive-issues">
         <span>False Positive</span>
         <span class="number">{{component.msr.false_positive_issues}}</span>
         <i class="icon-chevron-right"></i>
index d4e2ffa911b3254654ac4acfa36a11a3742754c6..5ea426ecee71d30f19358fedf9ff5d0c59afb342 100644 (file)
@@ -70,10 +70,12 @@ define(['handlebars'], function (Handlebars) {
   });
 
   Handlebars.registerHelper('inArray', function(array, element, options) {
-    if (array.indexOf(element) !== -1) {
-      return options.fn(this);
-    } else {
-      return options.inverse(this);
+    if (_.isArray(array)) {
+      if (array.indexOf(element) !== -1) {
+        return options.fn(this);
+      } else {
+        return options.inverse(this);
+      }
     }
   });
 
index c03cb85fde24732320cdb207b666a3dae1891909..105ef9d16bff587660d64100754a702cecf565cc 100644 (file)
@@ -156,7 +156,7 @@ define(
                 jQuery('.navigator-details').removeClass('navigator-fetching');
                 app.detailsRegion.show(componentViewer);
                 componentViewer.open(that.model.get('component')).done(function() {
-                  componentViewer.showIssues([that.model.toJSON()], true);
+                  componentViewer.showIssues(that.model.toJSON(), true);
 
                   var row = componentViewer.$('.code-issue:first').closest('.row');
                   if (row.data('line-number') > 0) {