]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5209 Add ability to create manual issues
authorStas Vilchik <vilchiks@gmail.com>
Wed, 18 Jun 2014 10:42:34 +0000 (16:42 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Wed, 18 Jun 2014 10:42:44 +0000 (16:42 +0600)
sonar-core/src/main/resources/org/sonar/l10n/core.properties
sonar-server/src/main/coffee/component-viewer/line-actions-popup.coffee [new file with mode: 0644]
sonar-server/src/main/coffee/component-viewer/source.coffee
sonar-server/src/main/coffee/issues/manual-issue-view.coffee [new file with mode: 0644]
sonar-server/src/main/hbs/component-viewer/line-options-popup.hbs [new file with mode: 0644]
sonar-server/src/main/hbs/issues/manual-issue.hbs [new file with mode: 0644]
sonar-server/src/main/less/component-viewer.less
sonar-server/src/main/less/style.less
sonar-server/src/main/less/ui.less

index 43edcb32e8c4c445fd03400d34651206a3874741..fdd8d4224a19c9643708d2326ba35941e07b06a1 100644 (file)
@@ -2650,6 +2650,8 @@ component_viewer.transition.duplication=Duplicated By
 
 component_viewer.x_lines_are_covered={0} lines are covered
 component_viewer.details=Details
+component_viewer.add_manual_issue=Add Manual Issue
+component_viewer.line_actions=Line Actions
 
 component_viewer.workspace=Workspace
 component_viewer.workspace.tooltip=Keeps track of history of navigation
diff --git a/sonar-server/src/main/coffee/component-viewer/line-actions-popup.coffee b/sonar-server/src/main/coffee/component-viewer/line-actions-popup.coffee
new file mode 100644 (file)
index 0000000..156ef17
--- /dev/null
@@ -0,0 +1,43 @@
+define [
+  'backbone.marionette'
+  'templates/component-viewer'
+  'component-viewer/popup'
+  'issues/manual-issue-view'
+], (
+  Marionette
+  Templates
+  Popup
+  ManualIssueView
+) ->
+
+  $ = jQuery
+
+
+  class extends Popup
+    template: Templates['line-options-popup']
+
+
+    events:
+      'click .js-add-manual-issue': 'addManualIssue'
+
+
+    addManualIssue: (e) ->
+      e.preventDefault()
+      line = @options.row.data 'line-number'
+      component = @options.main.component.get 'key'
+      manualIssueView = new ManualIssueView
+        line: line
+        component: component
+      manualIssueView.render().$el.appendTo @options.row.find('.line')
+      manualIssueView.on 'add', (issue) =>
+        issues = @options.main.source.get('issues') || []
+        activeIssues = @options.main.source.get('activeIssues') || []
+        showIssues = @options.main.settings.get 'issues'
+        issues.push issue
+        if showIssues then activeIssues.push issue else activeIssues = [issue]
+        @options.main.source.set 'issues', issues
+        @options.main.source.set 'activeIssues', activeIssues
+        @options.main.settings.set 'issues', true
+        @options.main.sourceView.render()
+
+
index ba33b45e391f1897b0f62256e2a122a765aae514..7d2070fc09f89c40f493405e1e60708e0d74d96a 100644 (file)
@@ -4,6 +4,7 @@ define [
   'component-viewer/coverage-popup'
   'component-viewer/duplication-popup'
   'component-viewer/time-changes-popup'
+  'component-viewer/line-actions-popup'
   'issues/issue-view'
   'issues/models/issue'
   'common/handlebars-extensions'
@@ -13,6 +14,7 @@ define [
   CoveragePopupView
   DuplicationPopupView
   TimeChangesPopupView
+  LineActionsPopupView
   IssueView
   Issue
 ) ->
@@ -69,6 +71,7 @@ define [
       @showSettings = false
       @renderExpandButtons()
       @renderIssues() if @options.main.settings.get('issues') && @model.has('activeIssues')
+      @highlightCurrentLine()
 
 
     renderExpandButtons: ->
@@ -114,9 +117,27 @@ define [
       @$el.html '<div style="padding: 10px;"><i class="spinner"></i></div>'
 
 
+    showLineActionsPopup: (e) ->
+      e.stopPropagation()
+      $('body').click()
+      popup = new LineActionsPopupView
+        triggerEl: $(e.currentTarget)
+        main: @options.main
+        row: $(e.currentTarget).closest '.row'
+      popup.render()
+
+
     highlightLine: (e) ->
       @$(".#{HIGHLIGHTED_ROW_CLASS}").removeClass HIGHLIGHTED_ROW_CLASS
-      $(e.currentTarget).closest('.row').addClass HIGHLIGHTED_ROW_CLASS
+      row = $(e.currentTarget).closest('.row')
+      row.addClass HIGHLIGHTED_ROW_CLASS
+      @highlightedLine = row.data 'line-number'
+      @showLineActionsPopup(e)
+
+
+    highlightCurrentLine: ->
+      if @highlightedLine?
+        @$("[data-line-number=#{@highlightedLine}]").addClass HIGHLIGHTED_ROW_CLASS
 
 
     highlightUsages: (e) ->
diff --git a/sonar-server/src/main/coffee/issues/manual-issue-view.coffee b/sonar-server/src/main/coffee/issues/manual-issue-view.coffee
new file mode 100644 (file)
index 0000000..6b82f16
--- /dev/null
@@ -0,0 +1,79 @@
+define [
+  'backbone.marionette'
+  'templates/issues'
+], (
+  Marionette
+  Templates
+) ->
+
+  $ = jQuery
+  API_ISSUE = "#{baseUrl}/api/issues/show"
+  API_ADD_MANUAL_ISSUE = "#{baseUrl}/api/issues/create"
+
+
+  class extends Marionette.ItemView
+    template: Templates['manual-issue']
+
+
+    events:
+      'submit .js-manual-issue-form': 'formSubmit'
+      'click .js-cancel': 'cancel'
+
+
+    onRender: ->
+      @delegateEvents()
+      @$('[name=rule]').select2
+        width: '250px'
+        minimumResultsForSearch: 10
+
+
+    showSpinner: ->
+      @$('.js-submit').hide()
+      @$('.js-spinner').show()
+
+
+    hideSpinner: ->
+      @$('.js-submit').show()
+      @$('.js-spinner').hide()
+
+
+    validateFields: ->
+      message = @$('[name=message]')
+      unless message.val()
+        message.addClass('invalid').focus()
+        return false
+      return true
+
+
+    formSubmit: (e) ->
+      e.preventDefault()
+      return unless @validateFields()
+      @showSpinner()
+      data = $(e.currentTarget).serialize()
+      $.post API_ADD_MANUAL_ISSUE, data
+        .done (r) =>
+          @addIssue r.issue.key
+        .fail (r) =>
+          @hideSpinner()
+          if r.responseJSON?.errors?
+            @showError _.pluck(r.responseJSON.errors, 'msg').join '. '
+
+
+    addIssue: (key) ->
+      $.get API_ISSUE, key: key, (r) =>
+        @trigger 'add', r.issue
+        @close()
+
+
+    showError: (msg) ->
+      @$('.code-issue-errors').removeClass('hidden').text msg
+
+
+    cancel: ->
+      @close()
+
+
+    serializeData: ->
+      _.extend super,
+        line: @options.line
+        component: @options.component
diff --git a/sonar-server/src/main/hbs/component-viewer/line-options-popup.hbs b/sonar-server/src/main/hbs/component-viewer/line-options-popup.hbs
new file mode 100644 (file)
index 0000000..eccd2e2
--- /dev/null
@@ -0,0 +1,9 @@
+<div class="component-viewer-popup-container">
+  <div class="component-viewer-popup-title">{{t 'component_viewer.line_actions'}}</div>
+
+  <div class="component-viewer-popup-section">
+    <a href="#" class="js-add-manual-issue link-action">{{t 'component_viewer.add_manual_issue'}}</a>
+  </div>
+</div>
+
+<div class="component-viewer-popup-arrow"></div>
\ No newline at end of file
diff --git a/sonar-server/src/main/hbs/issues/manual-issue.hbs b/sonar-server/src/main/hbs/issues/manual-issue.hbs
new file mode 100644 (file)
index 0000000..bb6fcc1
--- /dev/null
@@ -0,0 +1,47 @@
+<form action="" class="js-manual-issue-form code-issue-create-form">
+  {{! no manual rules }}
+  {{! <div class="warning" style="margin: 10px"> }}
+  {{!   <% if is_admin %> }}
+  {{!   <%= message('issue.manual.no_rules.admin') -%> }}
+  {{!   &nbsp;<a href="<%= ApplicationController.root_context -%>/manual_rules/index"><%= message('manage') -%></a> }}
+  {{!   <% else %> }}
+  {{!   <%= message('issue.manual.no_rules.non_admin') -%> }}
+  {{!   <% end %> }}
+  {{!   &nbsp;<%= link_to_function message('cancel'), 'closeCreateIssueForm(this)' -%> }}
+  {{! </div> }}
+
+  <input type="hidden" name="line" value="{{line}}">
+  <input type="hidden" name="component" value="{{component}}">
+
+  <div class="code-issue-name">
+    {{! TODO: replace mock data }}
+    <select name="rule">
+      <option value="manual:api">API</option>
+      <option value="manual:design">Design</option>
+      <option value="manual:error_handling">Error handling</option>
+      <option value="manual:performance">Performance</option>
+      <option value="manual:sql_pitfalls">SQL Pitfall</option>
+    </select>
+  </div>
+
+  <div class="code-issue-msg">
+    <table class="width100">
+      <tr>
+        <td>
+          <textarea rows="4" name="message" class="width100 marginbottom5"></textarea>
+        </td>
+      </tr>
+      <tr>
+        <td class="js-submit">
+          <input type="submit" value="{{t 'create'}}">
+          <a class="js-cancel" href="#">{{t 'cancel'}}</a>
+        </td>
+        <td class="js-spinner" style="display: none;">
+          <i class="spinner"></i>
+        </td>
+      </tr>
+    </table>
+    <div class="code-issue-errors error hidden"></div>
+  </div>
+
+</form>
index 6cae4991a822c14e3e50ad96d2e78e8bcce7a5d5..30f0434027a72b4a3ece329ab3d9c93bed223e1a 100644 (file)
     td.line { background-color: @barBackgroundColor; }
   }
 
-  .code .row-highlighted {
-    td.stat { background-color: #e9e94d !important; }
-    td.line { background-color: #f1f1a3 !important; }
+  .code .row-highlighted,
+  .code .row-highlighted:hover {
+    td.stat { background-color: #e9e94d; }
+    td.line { background-color: #f1f1a3; }
   }
 
   .code td.line {
   .code .stat {
 
     &.coverage-green {
-      background-color: lighten(@green, 15%);
+      background-color: lighten(@green, 15%) !important;
       color: @baseFontColor;
     }
 
     &.coverage-orange {
-      background-color: lighten(@orange, 15%);
+      background-color: lighten(@orange, 15%) !important;
       color: @baseFontColor;
     }
 
     &.coverage-red {
-      background-color: lighten(@red, 15%);
+      background-color: lighten(@red, 15%) !important;
       color: @baseFontColor;
     }
   }
 
 .component-viewer-popup-section {
   width: 450px;
+  padding-bottom: 2px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
index 85f9005f50208b74274fa738142e2a6d6bd0f5fd..4581fd64b1649e58140624cd0890fea7838e7b88 100644 (file)
@@ -1011,6 +1011,10 @@ th.operations, td.operations {
   display: none;
 }
 
+.code-issue-errors {
+  margin-top: 10px;
+}
+
 .tab_header {
   border-bottom: 1px solid #DDD;
   background-color: #EFEFEF;
index 67a4ab3e7814b67bdbba07e0dd912ae17dcf8b89..bdab9e2c93559553850acd8de770cb1e1b037e8f 100644 (file)
@@ -151,6 +151,8 @@ textarea {
     box-shadow: none;
     outline: none;
   }
+
+  &.invalid { border-color: @red; }
 }
 
 input[type=text],