From ff5e88095a37da7f8744652f2af9423c4822da22 Mon Sep 17 00:00:00 2001 From: simonbrandhof Date: Tue, 6 Dec 2011 17:01:12 +0100 Subject: [PATCH] SONAR-1974 add the form to create its own violations --- .../app/controllers/drilldown_controller.rb | 6 +- .../app/controllers/resource_controller.rb | 29 ++- .../app/views/drilldown/_header.html.erb | 2 +- .../app/views/drilldown/measures.html.erb | 1 + .../app/views/drilldown/violations.html.erb | 9 +- .../resource/_create_violation_form.html.erb | 31 +++ .../app/views/resource/_javascript.html.erb | 26 +++ .../app/views/resource/_violation.html.erb | 14 +- .../WEB-INF/app/views/resource/index.html.erb | 209 +++++++++--------- .../WEB-INF/app/views/reviews/index.html.erb | 2 + .../WEB-INF/app/views/source/_source.html.erb | 3 +- .../main/webapp/javascripts/application.js | 57 +---- .../src/main/webapp/stylesheets/style.css | 33 ++- 13 files changed, 238 insertions(+), 184 deletions(-) create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/resource/_create_violation_form.html.erb create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb index b35c5378c16..3671f1dd71a 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb @@ -79,10 +79,10 @@ class DrilldownController < ApplicationController end @severity = params[:severity] || params[:priority] - rule_severity = params[:rule_sev] || @severity - if rule_severity + @rule_severity = params[:rule_sev] || @severity + if @rule_severity # Filter resources by severity - @metric = Metric::by_key("#{metric_prefix}#{rule_severity.downcase}_violations") + @metric = Metric::by_key("#{metric_prefix}#{@rule_severity.downcase}_violations") else @metric = Metric::by_key("#{metric_prefix}violations") end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb index abe5ef95921..9ff6c07732e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb @@ -26,6 +26,8 @@ class ResourceController < ApplicationController SECTION=Navigation::SECTION_RESOURCE helper :dashboard, SourceHelper + verify :method => :post, :only => [:create_violation] + def index @resource = Project.by_key(params[:id]) not_found("Resource not found") unless @resource @@ -64,6 +66,30 @@ class ResourceController < ApplicationController :group_index => params[:group_index], :external => (resource.root_id != original_resource.root_id)} end + # Ajax request to display a form to create a review anywhere in source code + # + #== Parameters + # + # * 'resource' + # * 'line' + def show_create_violation_form + @line = params[:line].to_i + @colspan = params[:colspan].to_i + render :partial => 'resource/create_violation_form' + end + + def create_violation + resource = Project.by_key(params[:resource]) + access_denied unless resource && current_user + rule = Review.find_or_create_rule(params[:category]) + violation = RuleFailure.create_manual!(resource, rule, params) + violation.create_review!( + :assignee => current_user, + :user => current_user, + :status => Review::STATUS_OPEN, + :manual_violation => true) + redirect_to :action => 'index', :id => resource.id + end private @@ -95,7 +121,7 @@ class ResourceController < ApplicationController def load_sources @period = params[:period].to_i unless params[:period].blank? @expanded=(params[:expand]=='true') - + @display_manual_violation_form=(current_user && has_role?(:user, @snapshot)) if @snapshot.source source_lines=@snapshot.source.syntax_highlighted_lines() init_scm() @@ -254,6 +280,7 @@ class ResourceController < ApplicationController end end + # Format before sonar 2.12 def parse_duplications_old_format(dups, duplication_groups) resource_by_key = {} dups.elements.each("duplications/duplication") do |dup| diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb index 14ffdf49594..0545dff41c7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb @@ -1,7 +1,7 @@ <%= render :partial => 'gwt/base', :locals => {:resource => nil, :popup => false, :metric => @metric.key} -%> <%= render :partial => 'gwt/resource_viewers' -%> - \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb index b692a19a301..9d3c1ff5cc5 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb @@ -7,32 +7,32 @@ <%= image_tag("priority/" + violation.failure_level.to_s + '.png') -%>   - <%= image_tag("sep12.png") -%> +   > <%= h(violation.rule.name) -%>   - <%= image_tag("sep12.png") -%> +   <% if violation.created_at %> <%= distance_of_time_in_words_to_now(violation.created_at) -%>   <% end %> <% if violation.switched_off? %> - <%= image_tag("sep12.png") -%> +   <%= message('false_positive') -%>   <% end %> <% if violation.review && violation.review.isReopened? %> - <%= image_tag("sep12.png") -%> +   <%= message('reopened') -%>   <% end %> <% if violation.review && violation.review.assignee_id %> - <%= image_tag("sep12.png") -%> +   <%= message('assigned_to') -%>: <%= h(violation.review.assignee.name) -%>   @@ -40,7 +40,7 @@ <% if current_user %> - <%= image_tag("sep12.png") -%> + <% if violation.review unless violation.switched_off? @@ -95,7 +95,7 @@ <% if is_last_comment && current_user %>    - <%= image_tag("sep12.png") -%> +    <%= link_to_remote message('add_comment'), :url => { :controller => "reviews", :action => "violation_comment_form", :id => violation.id }, diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb index fd76f702500..b4c45d7c70c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb @@ -1,8 +1,7 @@ <%= render :partial => 'tabs' -%> - +<%= render :partial => 'resource/javascript' -%> <%= render :partial => "resource/header_#{@extension.getId()}" -%> - <% if @display_violations && @global_violations && @global_violations.size>0 -%> <% @global_violations.each do |violation| %> @@ -13,120 +12,128 @@
<% end %> - <% if @lines && @lines.size>0 %> - - <% - current_revision=nil - colspan=2 - colspan+=1 if @scm_available - colspan+=2 if @display_coverage - previous_hidden=false - first_section=true - has_displayed_lines=false - @lines.each_with_index do |line, index| - if line.hidden? && !@expanded - previous_hidden=true - next - end - - if previous_hidden && !first_section +
+ <% + colspan=2 + colspan+=1 if @display_manual_violation_form + colspan+=1 if @scm_available + colspan+=2 if @display_coverage + violation_form_colspan=(@scm_available ? 3 : 2) current_revision=nil -%> - - - -<% - end - previous_hidden=false - first_section=false + previous_hidden=false + first_section=true + has_displayed_lines=false + @lines.each_with_index do |line, index| + if line.hidden? && !@expanded + previous_hidden=true + next + end - status=hits_status=conditions_status='' - if line.highlighted? - has_displayed_lines=true - if @display_coverage && line.hits - hits_status=(line.hits>0 ? 'ok' : 'ko') - if line.conditions && line.conditions>0 && line.covered_conditions - if line.covered_conditions==0 - status='ko' - conditions_status='ko' - elsif line.covered_conditions==line.conditions - status='' - conditions_status='ok' - else - conditions_status='warn' - status='warn' - end - elsif line.hits - status=(line.hits>0 ? '' : 'ko') - end - elsif @display_violations && line.violations? - status="ko" - end - end - %> - - <% - if @scm_available - if current_revision!=line.revision - current_revision=line.revision - title = "Revision #{h(line.revision)}" + if previous_hidden && !first_section + current_revision=nil %> - - <% else %> + + + + <% + end + previous_hidden=false + first_section=false + + status=hits_status=conditions_status='' + if line.highlighted? + has_displayed_lines=true + if @display_coverage && line.hits + hits_status=(line.hits>0 ? 'ok' : 'ko') + if line.conditions && line.conditions>0 && line.covered_conditions + if line.covered_conditions==0 + status='ko' + conditions_status='ko' + elsif line.covered_conditions==line.conditions + status='' + conditions_status='ok' + else + conditions_status='warn' + status='warn' + end + elsif line.hits + status=(line.hits>0 ? '' : 'ko') + end + elsif @display_violations && line.violations? + status="ko" + end + end + %> + + <% if @display_manual_violation_form %> + + <% + end + if @scm_available + if current_revision!=line.revision + current_revision=line.revision + title = "Revision #{h(line.revision)}" + %> + + <% else %> - <% end - end - %> - + <% end + end + %> + - <% if @display_coverage %> - <% if line.highlighted? %> - - + + <% else %> + + + <% end %> <% end %> - - <% else %> - - + + + <% if @display_violations && line.violations? %> + + <% if @display_manual_violation_form %> + + <% end + if @scm_available %> + + <% end %> + + + <% end %> <% end %> - - - <% if @display_violations && line.violations? %> - - <% if @scm_available %> - - <% end %> - - - - <% end %> - <% end %> -
<%= Java::OrgSonarApiUtils::DateUtils.formatDate(line.datetime) if line.datetime -%> <%= h(line.author) -%>
+ <%= Java::OrgSonarApiUtils::DateUtils.formatDate(line.datetime) if line.datetime -%> + <%= h(line.author) -%><%= index + 1 -%><%= index + 1 -%> + <%= line.hits -%> - <% if line.deprecated_conditions_label -%> - <%= line.deprecated_conditions_label -%> - <% elsif line.conditions && line.conditions>0 -%> - <%= line.covered_conditions -%>/<%= line.conditions -%> + <% if @display_coverage %> + <% if line.highlighted? %> + <%= line.hits -%> + <% if line.deprecated_conditions_label -%> + <%= line.deprecated_conditions_label -%> + <% elsif line.conditions && line.conditions>0 -%> + <%= line.covered_conditions -%>/<%= line.conditions -%> + <% end %> + +
<%= line.source -%>
+
+ <% line.violations.each_with_index do |violation, index| %> + <%= render :partial => 'violation', :locals => {:violation => violation} -%> + <% if index < line.violations.size-1 %> +   + <% end %> + <% end %> +
-
<%= line.source -%>
-
- <% line.violations.each_with_index do |violation, index| %> - <%= render :partial => 'violation', :locals => {:violation => violation} -%> - <% if index < line.violations.size-1 %> -   - <% end %> - <% end %> -
+ <% if @filtered && !has_displayed_lines %> -

<%= message('no_lines_match_your_filter_criteria') -%>

+

<%= message('no_lines_match_your_filter_criteria') -%>

<% end %> - + <% end %> <% if @duplication_groups %> - <%= render :partial => 'duplications' -%> - <% end %> \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/index.html.erb index dd2cbd7d1df..31f0acbb95c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/index.html.erb @@ -160,10 +160,12 @@ function launchSearch(columnName, link) { <%= link_to h(review.title), :controller => "reviews", :action => "view", :id => review.id -%> + <% if comment %>
 <%= comment.user.name -%> : <%= comment.excerpt -%> + <% end %>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/source/_source.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/source/_source.html.erb index 3a1b1cd9432..22ec14dd12e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/source/_source.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/source/_source.html.erb @@ -1,4 +1,3 @@ - <% if !panel.empty? %> <% @@ -47,7 +46,7 @@ <% end end %> - +
<%= line.id -%><%= line.id -%> diff --git a/sonar-server/src/main/webapp/javascripts/application.js b/sonar-server/src/main/webapp/javascripts/application.js index 5927f31860f..d89efd1fdba 100644 --- a/sonar-server/src/main/webapp/javascripts/application.js +++ b/sonar-server/src/main/webapp/javascripts/application.js @@ -1,61 +1,6 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults -function registerAjaxErrors() { - var Messages = { - lastMessageId: 0, - lastRequestLastMessageId: 0, - - onComplete: function(request, transport, json) { - this.extractMessages(json); - }, - - onFailure: function(request, transport, json) { - this.extractMessages(json); - }, - - extractMessages: function(json) { - target = json['target']; - if ( target == null ) { - target = 'messages'; - } - - for (msgClass in json) { - if ( msgClass == 'target' ) continue; - msgsOfClass = typeof( json[msgClass] ) == 'string' ? new Array(json[msgClass]) : json[msgClass]; - for (var i = 0; i < msgsOfClass.length; i++) { - this.displayMessage(target,msgClass, msgsOfClass[i]); - } - } - this.lastRequestLastMessageId = this.lastMessageId; - }, - - displayMessage: function(target, msgClass, msgText) { - if (this.lastMessageId == this.lastRequestLastMessageId) { - msgEls = $A($(target).getElementsByTagName('li')); - for (var i = 0; i < msgEls.length; i++) { - Effect.Fade(msgEls[i].id, { afterFinish: function() {Element.remove(msgEls[i]);} } ); - } - } - - msgId = 'message-' + ++this.lastMessageId; - liEl = document.createElement('li'); - liEl.setAttribute('id', msgId); - liEl.setAttribute('class', msgClass); - liEl.setAttribute('title', "Click to close."); - liEl.setAttribute('onclick', 'Element.remove(this);'); - liEl.setAttribute('style', 'cursor: pointer;'); - liEl.appendChild( document.createTextNode(msgText) ); - - $(target).appendChild(liEl); - } - }; - - Ajax.Responders.register(Messages); -} function displayImage(imageId, imageUrl) { var newImage = new Image(); newImage.src = imageUrl; - //$(imageId).src = '../../images/loading.gif'; new PeriodicalExecuter(function(pe) { if (newImage.complete) { $(imageId).src = imageUrl; @@ -243,4 +188,4 @@ var SelectBox = { box.options[i].selected = 'selected'; } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/sonar-server/src/main/webapp/stylesheets/style.css b/sonar-server/src/main/webapp/stylesheets/style.css index a48a8d4f8de..d2afd594de5 100644 --- a/sonar-server/src/main/webapp/stylesheets/style.css +++ b/sonar-server/src/main/webapp/stylesheets/style.css @@ -838,7 +838,6 @@ ul.operations li img { text-decoration: none; color: #AAA; } - .sources2 td.scm { border-right: 1px solid #DDD; border-left: 1px solid #DDD; @@ -851,35 +850,53 @@ ul.operations li img { padding: 0 0.3em; white-space: nowrap; } - +.sources2 tr.row td.plus { + background-color: #ECECEC; + border-left: 1px solid #DDD; + padding: 0; + width: 16px; +} +.sources2 tr.row:hover td.plus { + background: url("../images/add.png") no-repeat scroll left 50% #ECECEC; +} +.sources2 td.plus a { + display: block; + cursor: pointer; + height: 16px; + width: 16px; +} +.sources2 td.nothing { + border-left: 1px solid #DDD; + background-color: #ECECEC; + padding: 2px 0.5em 0; +} .sources2 span.date, .sources2 span.date a { color: #AAA; font-size: 85%; text-decoration: none; } - .sources2 span.author, .sources2 span.author a { font-size: 85%; } - .sources2 div.violation, #global_violations div.violation { background-color: #FFF; margin: 0; border: 1px solid #DDD; } - .sources2 div.violation .actions, #global_violations div.violation .actions { visibility: hidden; } - .sources2 div.violation:hover .actions, #global_violations div.violation:hover .actions { visibility: visible; } - .sources2 div.violation .actions form, #global_violations div.violation .actions form { display: inline; visibility: visible; } +.sources2 td.reviewForm { + width: 100%; + padding: 10px; +} div.vtitle { background-color: #E4ECF3; @@ -969,8 +986,6 @@ span.rulename a:hover { .sources2 td.ok { background-color: #ACE97C; - border-top: 1px solid #6EC563; - border-bottom: 1px solid #6EC563; } .sources2 td.warn { -- 2.39.5