aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice Bellingard <bellingard@gmail.com>2011-12-19 16:21:22 +0100
committerFabrice Bellingard <bellingard@gmail.com>2011-12-19 16:22:20 +0100
commit17a932cde5030121ddec6094b9b89852152cefde (patch)
tree66cbf2ca1be1410896f5c6743177e56ff25f9520
parentc5edb54175be630d973a3a994e6cb44c46d3edfb (diff)
downloadsonarqube-17a932cde5030121ddec6094b9b89852152cefde.tar.gz
sonarqube-17a932cde5030121ddec6094b9b89852152cefde.zip
SONAR-2662 Make it possible to assign a review to an action plan
- From the resource viewer - From the review detail/permalink page
-rw-r--r--plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties7
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb51
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/review.rb26
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb14
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb16
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb8
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_action_plan_form.html.erb16
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb15
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_action_plan_form.html.erb27
10 files changed, 180 insertions, 4 deletions
diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties
index 97bade0325a..ee60aff5462 100644
--- a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties
+++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties
@@ -400,6 +400,12 @@ reviews.status.OPEN=Open
reviews.status.CLOSED=Closed
reviews.resolution.FALSE-POSITIVE=False-positive
reviews.resolution.FIXED=Fixed
+reviews.link_to_action_plan=Action plan
+reviews.action_plan_label=Action plan
+reviews.action_plan_submit=Link to action plan
+reviews.no_action_plan=None
+reviews.planned_for_x=Planned for {0}
+reviews.planned_for_label=Planned for
#------------------------------------------------------------------------------
@@ -418,6 +424,7 @@ action_plans.col.description=Description
action_plans.col.author=Author
action_plans.col.operations=Operations
action_plans.no_action_plan=No action plan
+action_plans.no_reviews_linked_to_action_plan=No reviews linked to this action plan yet.
action_plans.confirm_delete=Delete this action plan? Associated reviews will not be deleted.
action_plans.create_new_action_plan=Create a new action plan
action_plans.date_format_help=The date should be entered using the following pattern: 'day/month/year'. For instance, '31/12/2011'.
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
index c8db5e02216..65ac6dfa25e 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
@@ -25,7 +25,8 @@ class ReviewsController < ApplicationController
verify :method => :post,
:only => [:assign, :flag_as_false_positive, :save_comment, :delete_comment, :change_status,
:violation_assign, :violation_flag_as_false_positive, :violation_change_severity,
- :violation_save_comment, :violation_delete_comment, :violation_change_status],
+ :violation_save_comment, :violation_delete_comment, :violation_change_status,
+ :violation_link_to_action_plan],
:redirect_to => {:action => :error_not_post}
helper SourceHelper, UsersHelper
@@ -186,6 +187,27 @@ class ReviewsController < ApplicationController
render :partial => "reviews/review"
end
+ # GET
+ def action_plan_form
+ @review = Review.find(params[:id])
+ @action_plans = ActionPlan.by_project_id(@review.project_id)
+ render :partial => 'reviews/action_plan_form'
+ end
+
+ # POST
+ def link_to_action_plan
+ @review = Review.find(params[:id])
+ unless has_rights_to_modify?(@review.project)
+ render :text => "<b>Cannot link to action plan</b> : access denied."
+ return
+ end
+
+ action_plan = params[:action_plan_id].to_i==-1 ? nil : ActionPlan.find(params[:action_plan_id])
+ @review.link_to_action_plan(action_plan, current_user, params)
+
+ render :partial => "reviews/review"
+ end
+
#
#
@@ -252,14 +274,12 @@ class ReviewsController < ApplicationController
render :partial => "resource/violation", :locals => {:violation => violation}
end
-
# GET
def violation_false_positive_form
@violation = RuleFailure.find(params[:id])
render :partial => 'reviews/violation_false_positive_form'
end
-
# POST
def violation_flag_as_false_positive
violation=RuleFailure.find(params[:id], :include => 'snapshot')
@@ -359,6 +379,31 @@ class ReviewsController < ApplicationController
render :partial => "resource/violation", :locals => {:violation => violation}
end
+ # GET
+ def violation_action_plan_form
+ @violation = RuleFailure.find(params[:id], :include => ['review', 'snapshot'])
+ @action_plans = ActionPlan.by_project_id(@violation.snapshot.root_project_id)
+ render :partial => 'reviews/violation_action_plan_form'
+ end
+
+ # POST
+ def violation_link_to_action_plan
+ violation = RuleFailure.find(params[:id], :include => 'snapshot')
+ unless has_rights_to_modify?(violation.snapshot)
+ render :text => "<b>Cannot link to action plan</b> : access denied."
+ return
+ end
+ sanitize_violation(violation)
+
+ if violation.review.nil?
+ violation.build_review(:user_id => current_user.id)
+ end
+ action_plan = params[:action_plan_id].to_i==-1 ? nil : ActionPlan.find(params[:action_plan_id])
+ violation.review.link_to_action_plan(action_plan, current_user, params)
+
+ render :partial => "resource/violation", :locals => {:violation => violation}
+ end
+
#
#
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb
index 72046216539..847178da0c7 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb
@@ -33,6 +33,10 @@ class ActionPlan < ActiveRecord::Base
STATUS_OPEN = 'OPEN'
STATUS_CLOSED = 'CLOSED'
+ def self.by_project_id(project_id)
+ ActionPlan.find :all, :conditions => ['project_id=?', project_id], :order => :name
+ end
+
def user
@user ||=
begin
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
index e7dcdae8766..9c05675324e 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
@@ -201,6 +201,19 @@ class Review < ActiveRecord::Base
notification_manager.notifyChanged(id.to_i, user.login.to_java, old, to_java_map("comment" => options[:text]))
end
+ def link_to_action_plan(action_plan, user, options={})
+ if options[:text].present?
+ comments.create!(:user => user, :text => options[:text])
+ end
+ old = self.to_java_map
+ self.action_plans.clear
+ if action_plan
+ self.action_plans << action_plan
+ end
+ self.save!
+ notification_manager.notifyChanged(id.to_i, user.login.to_java, old, to_java_map("action_plans" => action_plan ? action_plan.name : ''))
+ end
+
def resolved?
status == STATUS_RESOLVED
end
@@ -216,6 +229,19 @@ class Review < ActiveRecord::Base
def open?
status == STATUS_OPEN
end
+
+ def linked_to? (action_plan)
+ action_plans.include? action_plan
+ end
+
+ def planned?
+ action_plans.size!=0
+ end
+
+ # used as long as we currently allow to link a review to only 1 action plan.
+ def action_plan
+ action_plans[0]
+ end
#
#
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb
index 3e4b74dcf54..61b62974a37 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb
@@ -5,7 +5,13 @@
#actionPlans td.progress {
width: 300px;
padding: 0px 40px;
- }
+ }
+ #actionPlans td.noprogress {
+ color: #777777;
+ font-size: 93%;
+ padding-left: 40px;
+ padding-right: 40px;
+ }
</style>
<div class="line-block marginbottom10">
@@ -41,9 +47,15 @@
<td class="thin nowrap center"><img src="<%= ApplicationController.root_context -%>/images/status/<%= plan.status -%>.png" title="<%= message(plan.status.downcase).capitalize -%>"/></td>
<td class="thin nowrap"><%= h(plan.name) -%></td>
<td class="thin nowrap" align="right" x="<%= plan.dead_line ? plan.dead_line.tv_sec : '' -%>"><%= plan.dead_line ? l(plan.dead_line) : ' ' -%></td>
+ <% if plan.progress[:total]==0 %>
+ <td class="noprogress thin nowrap">
+ <%= message('action_plans.no_reviews_linked_to_action_plan') -%>
+ </td>
+ <% else %>
<td class="progress thin">
<%= render :partial => 'progress', :locals => {:action_plan => plan} -%>
</td>
+ <% end %>
<td id="desc"><%= h(plan.description) -%></td>
<td id="desc"><%= h(plan.user.name) -%></td>
<td class="thin nowrap">
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb
index b68d442baa6..a4e72396f74 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb
@@ -117,6 +117,22 @@
return false;
}
+ // show the form to link a review to an action plan
+ function sAPF(violation_id) {
+ new Ajax.Updater('reviewForm' + violation_id,
+ '<%= ApplicationController.root_context -%>/reviews/violation_action_plan_form/' + violation_id,
+ {
+ asynchronous:true,
+ evalScripts:true,
+ onComplete:function (request) {
+ $('vBody' + violation_id).remove();
+ $('reviewForm' + violation_id).show();
+ $('action_plan').focus();
+ }
+ });
+ return false;
+ }
+
// show the form to create violation
function sVF(resource, line, gray_colspan, white_colspan) {
row = $('createViolationForm' + line);
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 7a150b1fe12..f92df046210 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
@@ -53,6 +53,12 @@
<%= message('assigned_to') -%> <%= h(violation.review.assignee.name) -%>
&nbsp;
<% end %>
+ <% if violation.review && violation.review.planned? %>
+ <img src="<%= ApplicationController.root_context -%>/images/sep12.png">
+ &nbsp;
+ <%= message('reviews.planned_for_x', :params => h(violation.review.action_plan.name)) -%>
+ &nbsp;
+ <% end %>
</div>
@@ -78,6 +84,8 @@
<% unless violation.review && violation.review.resolved? %>
<%= button_to_function message('reviews.change_severity'), "sCSF(#{violation.id})", :name => 'bChangeSeverity' -%>
+
+ <%= button_to_function message('reviews.link_to_action_plan'), "sAPF(#{violation.id})", :name => 'bLinkActionPlan' -%>
<% end %>
</div>
<% end %>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_action_plan_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_action_plan_form.html.erb
new file mode 100644
index 00000000000..5e6c95d3934
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_action_plan_form.html.erb
@@ -0,0 +1,16 @@
+<form method="POST">
+ <input type="hidden" name="id" value="<%= params[:id] -%>"/>
+
+ <%= message('reviews.action_plan_label') -%>:
+ <select name="action_plan_id" id="selectActionPlan">
+ <option value="-1" <%= 'selected' if !@review.planned? -%>><%= message('reviews.no_action_plan') -%></option>
+ <% @action_plans.each do |plan| %>
+ <option value="<%= plan.id -%>" <%= 'selected' if @review.linked_to?(plan) -%>><%= h(plan.name) -%></option>
+ <% end %>
+ </select>
+
+ <textarea id="actionText" rows="4" name="text" style="width: 100%"></textarea>
+ <%= submit_to_remote "submit_btn", message('reviews.action_plan_submit'), :url => {:action => 'link_to_action_plan'}, :html => {:id => "submit_btn"}, :update => 'review' -%>
+ &nbsp;
+ <%= link_to_remote message('cancel'), :url => {:action => 'show', :id => params[:id]}, :update => 'review' -%>
+</form>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb
index 567d6e01a41..6b2ef05584f 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb
@@ -38,6 +38,11 @@
:url => {:controller => "reviews", :action => "change_severity_form", :id => review.id},
:update => "actionForm",
:complete => "$('actionButtons').remove();$('actionForm').show();$('selectSeverity').focus();" -%>
+
+ <%= button_to_remote message('reviews.link_to_action_plan'),
+ :url => {:controller => "reviews", :action => "action_plan_form", :id => review.id},
+ :update => "actionForm",
+ :complete => "$('actionButtons').remove();$('actionForm').show();$('selectSeverity').focus();" -%>
<% end %>
</div>
<% end %>
@@ -90,6 +95,16 @@
<%= l(review.updated_at) -%>
</td>
</tr>
+ <% if review.planned? %>
+ <tr>
+ <td class="key">
+ <%= message('reviews.planned_for_label') -%>:
+ </td>
+ <td class="val" colspan="3">
+ <%= h(review.action_plan.name) -%>
+ </td>
+ </tr>
+ <% end %>
<% if review.rule %>
<tr>
<td class="key">
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_action_plan_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_action_plan_form.html.erb
new file mode 100644
index 00000000000..596ca7b9611
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_action_plan_form.html.erb
@@ -0,0 +1,27 @@
+<form method="POST" action="violation_link_to_action_plan">
+ <input type="hidden" name="id" value="<%= params[:id] -%>"/>
+
+ <%= message('reviews.action_plan_label') -%>:
+ <select name="action_plan_id" id="selectActionPlan<%= params[:id] -%>">
+ <option value="-1" <%= 'selected' if !@violation.review || (@violation.review && !@violation.review.planned?) -%>><%= message('reviews.no_action_plan') -%></option>
+ <% @action_plans.each do |plan| %>
+ <option value="<%= plan.id -%>" <%= 'selected' if @violation.review && @violation.review.linked_to?(plan) -%>><%= h(plan.name) -%></option>
+ <% end %>
+ </select>
+
+ <table class="width100">
+ <tr>
+ <td style="vertical-align:top">
+ <textarea id="commentText<%= params[:id] -%>" rows="4" name="text" style="width: 100%"></textarea>
+ </td>
+ <td class="sep"></td>
+ <td style="vertical-align:top;width: 90px">
+ <%= render :partial => 'markdown/help' -%>
+ </td>
+ </tr>
+ </table>
+
+ <%= submit_to_remote "submit_btn"+params[:id], message('reviews.action_plan_submit'), :url => {:action => 'violation_link_to_action_plan'}, :html => {:id => "submit_btn"+params[:id]}, :update => 'vId'+params[:id] -%>
+ &nbsp;
+ <%= link_to_function message('cancel'), "cancelViolationAction(#{params[:id]})" -%>
+</form>