aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server
diff options
context:
space:
mode:
authorFabrice Bellingard <bellingard@gmail.com>2011-12-20 17:11:10 +0100
committerFabrice Bellingard <bellingard@gmail.com>2011-12-20 17:13:03 +0100
commitc2102d5c5efe921fedf0f36b8aee49348f838cc5 (patch)
tree7264ae9dd73044313d695995124b971544d43cdf /sonar-server
parent604ec306443465b67ac40423921d04e5d1bc169e (diff)
downloadsonarqube-c2102d5c5efe921fedf0f36b8aee49348f838cc5.tar.gz
sonarqube-c2102d5c5efe921fedf0f36b8aee49348f838cc5.zip
SONAR-2662 Improve action plans
- The create/update form is now on the same page as the listing of the action plans (and on an orange background) - Must be possible to create action plans with the same name in different projects - Do not put links on '0' in the progress bar - Improve rendering of progress bar on Chrome - Display an alert message if one wants to plan a review whereas no action plan has been defined on the project - If only one action is available, select it automatically when planning a review - Add a "Unlink" button and remove the "none" entry in the select box - Add "Back" button on the review listing page - Fix bug on Derby with dead_line date
Diffstat (limited to 'sonar-server')
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/action_plans_controller.rb24
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb1
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb29
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb11
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_new.html.erb39
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_progress.html.erb24
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb124
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/new.html.erb65
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/project_reviews/index.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb9
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_action_plan_form.html.erb7
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb6
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_action_plan_form.html.erb7
13 files changed, 201 insertions, 149 deletions
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/action_plans_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/action_plans_controller.rb
index b27456c767b..1a9cfc1ec48 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/action_plans_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/action_plans_controller.rb
@@ -25,15 +25,13 @@ class ActionPlansController < ApplicationController
verify :method => :post, :only => [:save, :delete, :change_status], :redirect_to => {:action => :index}
def index
- @action_plans = ActionPlan.find(:all, :conditions => ['project_id=?', @resource.id], :include => 'reviews', :order => 'dead_line ASC')
+ load_action_plans()
end
- def new
- if params[:name] || params[:description] || params[:dead_line]
- @action_plan = ActionPlan.new
- elsif params[:plan_id]
- @action_plan = ActionPlan.find params[:plan_id]
- end
+ def edit
+ @action_plan = ActionPlan.find params[:plan_id]
+ load_action_plans()
+ render 'index'
end
def save
@@ -48,7 +46,7 @@ class ActionPlansController < ApplicationController
@action_plan.description = params[:description]
unless params[:dead_line].blank?
begin
- dead_line = Date.strptime(params[:dead_line], '%d/%m/%Y')
+ dead_line = DateTime.strptime(params[:dead_line], '%d/%m/%Y')
if dead_line.past?
date_not_valid = message('action_plans.date_cant_be_in_past')
else
@@ -60,8 +58,10 @@ class ActionPlansController < ApplicationController
end
if date_not_valid || !@action_plan.valid?
- @action_plan.errors.add :dead_line, date_not_valid if date_not_valid
- render :action => :new, :id => @resource.id
+ @action_plan.errors.add :base, date_not_valid if date_not_valid
+ flash[:error] = @action_plan.errors.full_messages.join('<br/>')
+ load_action_plans()
+ render 'index'
else
@action_plan.save
redirect_to :action => 'index', :id => @resource.id
@@ -90,5 +90,9 @@ class ActionPlansController < ApplicationController
return redirect_to home_path unless @resource
access_denied unless has_role?(:admin, @resource)
end
+
+ def load_action_plans
+ @action_plans = ActionPlan.find(:all, :conditions => ['project_id=?', @resource.id], :include => 'reviews', :order => 'dead_line ASC')
+ end
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 fcdf4c7f532..b2fd5af628c 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
@@ -321,6 +321,7 @@ class ResourceController < ApplicationController
@global_violations=[]
@expandable=(@lines!=nil)
@filtered=!@expanded
+ @action_plans_size=ActionPlan.open_by_project_id(@snapshot.root_project_id).size
conditions='snapshot_id=?'
values=[@snapshot.id]
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 21295789a0c..259e02061db 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
@@ -24,10 +24,10 @@ class ReviewsController < ApplicationController
verify :method => :post,
:only => [:assign, :flag_as_false_positive, :save_comment, :delete_comment, :change_status,
- :link_to_action_plan,
+ :link_to_action_plan, :unlink_from_action_plan,
:violation_assign, :violation_flag_as_false_positive, :violation_change_severity,
:violation_save_comment, :violation_delete_comment, :violation_change_status,
- :violation_link_to_action_plan],
+ :violation_link_to_action_plan, :violation_unlink_from_action_plan],
:redirect_to => {:action => :error_not_post}
helper SourceHelper, UsersHelper
@@ -208,6 +208,19 @@ class ReviewsController < ApplicationController
render :partial => "reviews/review"
end
+
+ # POST
+ def unlink_from_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
+
+ @review.link_to_action_plan(nil, current_user, params)
+
+ render :partial => "reviews/review"
+ end
#
@@ -404,6 +417,18 @@ class ReviewsController < ApplicationController
render :partial => "resource/violation", :locals => {:violation => violation}
end
+
+ # POST
+ def violation_unlink_from_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
+ violation.review.link_to_action_plan(nil, 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 73562567163..9e72e9b3b3b 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
@@ -22,12 +22,12 @@ class ActionPlan < ActiveRecord::Base
belongs_to :project
has_and_belongs_to_many :reviews
- validates_uniqueness_of :name
validates_length_of :name, :within => 1..200
validates_length_of :description, :maximum => 1000, :allow_blank => true, :allow_nil => true
validates_presence_of :user_login, :message => "can't be empty"
validates_presence_of :status, :message => "can't be empty"
validates_presence_of :project, :message => "can't be empty"
+ validate :unique_name_on_same_project
STATUS_OPEN = 'OPEN'
STATUS_CLOSED = 'CLOSED'
@@ -64,5 +64,14 @@ class ActionPlan < ActiveRecord::Base
def over_due?
dead_line ? status==STATUS_OPEN && dead_line.past? : false
end
+
+ private
+
+ def unique_name_on_same_project
+ action_plan = ActionPlan.find(:first, :conditions => ['project_id=? AND name=?', project_id, name])
+ if action_plan && ( (id && action_plan.id!=id) || !id)
+ errors.add(:base, Api::Utils.message('action_plans.same_name_in_same_project'))
+ end
+ end
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_new.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_new.html.erb
new file mode 100644
index 00000000000..a176974e9e7
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_new.html.erb
@@ -0,0 +1,39 @@
+<table class="admintable" width="100%">
+ <form action="<%= url_for :action => 'save' -%>" method="POST" id="create-action-plan-form">
+ <input type="hidden" name="id" value="<%= @resource.id -%>"/>
+ <input type="hidden" name="plan_id" value="<%= @action_plan.id if @action_plan -%>"/>
+ <tbody>
+ <tr>
+ <td colspan="2"><h1 class="marginbottom10"><%= @action_plan ? message('action_plans.edit_action_plan') : message('action_plans.create_new_action_plan') -%></h1></h1></td>
+ </tr>
+ <tr>
+ <td class="left" valign="top">
+ <%= message('action_plans.col.name') -%>:
+ <br/>
+ <input type="text" name="name" id="name" value="<%= @action_plan ? @action_plan.name : params[:name] -%>"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="left" valign="top">
+ <%= message('action_plans.col.due_for') -%>:
+ <br/>
+ <input type="text" name="dead_line" id="dead_line" value="<%= @action_plan && @action_plan.dead_line ? @action_plan.dead_line.strftime('%d/%m/%Y') : params[:dead_line] -%>"/>
+ <br/>
+ <span class="note"><%= message('action_plans.date_format_help') -%></span>
+ </td>
+ </tr>
+ <tr>
+ <td class="left" valign="top">
+ <%= message('action_plans.col.description') -%>:
+ <br/>
+ <textarea rows="5" cols="80" name="description" id="description" class="width100"><%= @action_plan ? @action_plan.description : params['description'] -%></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td class="left" valign="top">
+ <input type="submit" value="<%= @action_plan ? message('action_plans.edit_action_plan') : message('action_plans.create_action_plan') -%>"/>
+ </td>
+ </tr>
+ </tbody>
+ </form>
+</table> \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_progress.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_progress.html.erb
index 23bdfa2e52b..acb27dfee64 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_progress.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/_progress.html.erb
@@ -2,29 +2,37 @@
unless action_plan.progress[:total]==0
options = {:controller => 'project_reviews', :action => 'index', :action_plan_id => action_plan.id, :projects => action_plan.project_id}
- resolved_reviews_link = link_to action_plan.progress[:resolved].to_s, options.merge({:statuses => "#{Review::STATUS_RESOLVED},#{Review::STATUS_CLOSED}"})
+ resolved_reviews_link = action_plan.progress[:resolved].to_s
+ resolved_reviews_link = link_to action_plan.progress[:resolved].to_s, options.merge({:statuses => "#{Review::STATUS_RESOLVED},#{Review::STATUS_CLOSED}"}) unless action_plan.progress[:resolved]==0
total_reviews_link = link_to action_plan.progress[:total].to_s, options
- resolved_reviews_url = url_for options.merge({:statuses => "#{Review::STATUS_RESOLVED},#{Review::STATUS_CLOSED}"})
- open_reviews_url = url_for options.merge({:statuses => "#{Review::STATUS_OPEN},#{Review::STATUS_REOPENED}"})
+ if action_plan.progress[:resolved] > 0
+ resolved_reviews_url = url_for options.merge({:statuses => "#{Review::STATUS_RESOLVED},#{Review::STATUS_CLOSED}"})
+ percent_resolved = (action_plan.progress[:resolved]*100/action_plan.progress[:total]).to_i
+ tooltip_resolved = message('action_plans.resolved_reviews_x_percent', :params => [percent_resolved.to_s, action_plan.progress[:resolved].to_s])
+ end
- percent_resolved = (action_plan.progress[:resolved]*100/action_plan.progress[:total]).to_i
- percent_open = (action_plan.progress[:open]*100/action_plan.progress[:total]).to_i
-
- tooltip_resolved = message('action_plans.resolved_reviews_x_percent', :params => [percent_resolved.to_s, action_plan.progress[:resolved].to_s])
- tooltip_open = message('action_plans.open_reviews_x_percent', :params => [percent_open.to_s, action_plan.progress[:open].to_s])
+ if action_plan.progress[:open] > 0
+ open_reviews_url = url_for options.merge({:statuses => "#{Review::STATUS_OPEN},#{Review::STATUS_REOPENED}"})
+ percent_open = (action_plan.progress[:open]*100/action_plan.progress[:total]).to_i
+ tooltip_open = message('action_plans.open_reviews_x_percent', :params => [percent_open.to_s, action_plan.progress[:open].to_s])
+ end
%>
<div class="progress">
<table>
<tbody>
<tr>
+ <% if action_plan.progress[:resolved] > 0 %>
<td class="resolved" style="width:<%= percent_resolved -%>%;">
<a href="<%= resolved_reviews_url -%>" title="<%= tooltip_resolved -%>" alt="<%= tooltip_resolved -%>"></a>
</td>
+ <% end %>
+ <% if action_plan.progress[:open] > 0 %>
<td class="open" style="width:<%= percent_open -%>%;">
<a href="<%= open_reviews_url -%>" title="<%= tooltip_open -%>" alt="<%= tooltip_open -%>"></a>
</td>
+ <% end %>
</tr>
</tbody>
</table>
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 38ecf0abd7e..14d1bc9d357 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
@@ -1,63 +1,69 @@
-<div class="line-block marginbottom10">
- <ul class="operations">
- <li class="last">
- <%= image_tag 'add.png' -%>
- <%= link_to message('action_plans.add_action_plan'), {:action => 'new', :id => @resource.id}, {:id => 'addActionPlan'} -%>
- </li>
- </ul>
- <h1><%= message('action_plans.page_title') -%></h1>
-</div>
-
-<table class="width100 data sortable actionPlans" id="actionPlans">
- <thead>
+<table width="100%">
<tr>
- <th class="thin nowrap"><%= message('action_plans.col.status') -%></th>
- <th class="thin nowrap"><%= message('action_plans.col.name') -%></th>
- <th class="thin nowrap righticon" style="text-align: right"><%= message('action_plans.col.due_for') -%></th>
- <th class="nowrap nosort center"><%= message('action_plans.col.progress') -%></th>
- <th class="nowrap"><%= message('action_plans.col.description') -%></th>
- <th class="nowrap"><%= message('action_plans.col.author') -%></th>
- <th class="thin nowrap nosort"><%= message('action_plans.col.operations') -%></th>
- </tr>
- </thead>
- <tbody>
- <% if @action_plans.empty? %>
- <td colspan="7" class="even"><%= message('action_plans.no_action_plan') -%></td>
- <% end %>
- <%
- @action_plans.each do |plan|
- %>
- <tr>
- <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 <%= 'over-due' if plan.over_due? -%>" align="right" x="<%= plan.dead_line ? plan.dead_line.tv_sec : '' -%>"><%= plan.dead_line ? plan.dead_line.strftime("%d %b %Y") : ' ' -%></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">
- <% if plan.open? %>
- <%= link_to message('edit'), {:action => 'new', :id => @resource.id, :plan_id => plan.id}, {:class => 'action'} -%>
+ <td valign="top">
+
+ <h1><%= message('action_plans.page_title') -%></h1>
+
+ <table class="width100 data sortable actionPlans" id="actionPlans">
+ <thead>
+ <tr>
+ <th class="thin nowrap"><%= message('action_plans.col.status') -%></th>
+ <th class="thin nowrap"><%= message('action_plans.col.name') -%></th>
+ <th class="thin nowrap righticon" style="text-align: right"><%= message('action_plans.col.due_for') -%></th>
+ <th class="nowrap nosort center"><%= message('action_plans.col.progress') -%></th>
+ <th class="nowrap"><%= message('action_plans.col.description') -%></th>
+ <th class="nowrap"><%= message('action_plans.col.author') -%></th>
+ <th class="thin nowrap nosort"><%= message('action_plans.col.operations') -%></th>
+ </tr>
+ </thead>
+ <tbody>
+ <% if @action_plans.empty? %>
+ <td colspan="7" class="even"><%= message('action_plans.no_action_plan') -%></td>
<% end %>
- <%
- close_confirmation_message = {}
- if plan.open? && plan.has_open_reviews?
- close_confirmation_message = {:confirm => message('action_plans.confirm_close')}
- end
+ <%
+ @action_plans.each do |plan|
%>
- <%= link_to plan.open? ? message('action_plans.close') : message('action_plans.reopen'),
- {:action => 'change_status', :id => @resource.id, :plan_id => plan.id}, {:method => 'POST', :class => 'action'}.merge(close_confirmation_message) -%>
- <%= link_to message('delete'), {:action => 'delete', :id => @resource.id, :plan_id => plan.id}, {:method => 'POST', :confirm => message('action_plans.confirm_delete'), :class => 'action'} -%>
- </td>
- </tr>
- <% end %>
- </tbody>
+ <tr>
+ <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 <%= 'over-due' if plan.over_due? -%>" align="right" x="<%= plan.dead_line ? plan.dead_line.tv_sec : '' -%>"><%= plan.dead_line ? plan.dead_line.strftime("%d %b %Y") : ' ' -%></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 right">
+ <% if plan.open? %>
+ <%= link_to message('edit'), :action => 'edit', :id => @resource.id, :plan_id => plan.id, :class => 'action' -%>
+ <% end %>
+ <%
+ close_confirmation_message = {}
+ if plan.open? && plan.has_open_reviews?
+ close_confirmation_message = {:confirm => message('action_plans.confirm_close')}
+ end
+ %>
+ <%= link_to plan.open? ? message('action_plans.close') : message('action_plans.reopen'),
+ {:action => 'change_status', :id => @resource.id, :plan_id => plan.id}, {:method => 'POST', :class => 'action'}.merge(close_confirmation_message) -%>
+ <%= link_to message('delete'), {:action => 'delete', :id => @resource.id, :plan_id => plan.id}, {:method => 'POST', :confirm => message('action_plans.confirm_delete'), :class => 'action'} -%>
+ </td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ <script>TableKit.Sortable.init('actionPlans');</script>
+
+ </td>
+ <td class="sep"></td>
+ <td width="210" valign="top" align="right">
+ <div id="admin_form">
+ <%= render :partial => 'new' %>
+ </div>
+ </td>
+ </tr>
</table>
-<script>TableKit.Sortable.init('actionPlans');</script>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/new.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/new.html.erb
deleted file mode 100644
index b2c62ddf370..00000000000
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/new.html.erb
+++ /dev/null
@@ -1,65 +0,0 @@
-<h1 class="marginbottom10"><%= message('action_plans.create_new_action_plan') -%></h1>
-
-<% if @action_plan && @action_plan.errors.on_base
- @action_plan.errors.on_base.each do |error| %>
- <div class="error"><%= error -%></div>
-<% end
- end
-%>
-
-<form action="<%= url_for :action => 'save' -%>" method="POST" id="createForm">
- <input type="hidden" name="id" value="<%= @resource.id -%>"/>
- <input type="hidden" name="plan_id" value="<%= @action_plan.id if @action_plan -%>"/>
- <table class="width100 form">
- <tbody>
- <tr>
- <td class="keyCell">
- <%= message('action_plans.col.name') -%>:
- </td>
- <td>
- <input type="text" name="name" id="name" value="<%= @action_plan ? @action_plan.name : '' -%>"/>
- <% if @action_plan && @action_plan.errors.on('name')
- @action_plan.errors.on('name').each do |error| %>
- <span class="error"><%= error -%></span>
- <% end
- end %>
- </td>
- </tr>
- <tr>
- <td class="keyCell">
- <%= message('action_plans.col.due_for') -%>:
- </td>
- <td>
- <input type="text" name="dead_line" id="dead_line" value="<%= @action_plan && @action_plan.dead_line ? @action_plan.dead_line.strftime('%d/%m/%Y') : params[:dead_line] -%>"/>
- <span class="note"><%= message('action_plans.date_format_help') -%></span>
- <% if @action_plan && @action_plan.errors.on('dead_line')
- @action_plan.errors.on('dead_line').each do |error| %>
- <span class="error"><%= error -%></span>
- <% end
- end %>
- </td>
- </tr>
- <tr>
- <td class="keyCell">
- <%= message('action_plans.col.description') -%>:
- </td>
- <td>
- <textarea rows="5" cols="80" name="description" id="description" class="width100"><%= @action_plan ? @action_plan.description : '' -%></textarea>
- <% if @action_plan && @action_plan.errors.on('description')
- @action_plan.errors.on('description').each do |error| %>
- <span class="error"><%= error -%></span>
- <% end
- end %>
- </td>
- </tr>
- <tr>
- <td class="keyCell">
- </td>
- <td>
- <input type="submit" value="<%= message('save') -%>"/>
- <%= link_to message('cancel'), :action => 'index', :id => @resource.id -%>
- </td>
- </tr>
- </tbody>
- </table>
-</form> \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/project_reviews/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/project_reviews/index.html.erb
index de1a58170c3..ffc5d58a6e4 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/project_reviews/index.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/project_reviews/index.html.erb
@@ -1,3 +1,7 @@
+<div style="font-size: 85%; margin-bottom: 10px">
+ยป <a href="#" onclick="history.back()"><%= message('back') -%></a>
+</div>
+
<div id="reviews-search">
<h1><%= message('reviews') -%></h1>
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 f92df046210..5eb274529cd 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
@@ -85,7 +85,14 @@
<% 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' -%>
+ <%
+ @action_plans_size = ActionPlan.open_by_project_id(violation.review.project_id).size unless @action_plans_size
+ if @action_plans_size > 0
+ %>
+ <%= button_to_function message('reviews.link_to_action_plan'), "sAPF(#{violation.id})", :name => 'bLinkActionPlan' -%>
+ <% else %>
+ <input type="button" value="<%= message('reviews.link_to_action_plan') -%>" onclick="alert('<%= message('reviews.an_action_plan_must_be_created_first') -%>');" name="bLinkActionPlan">
+ <% end %>
<% 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
index 5e6c95d3934..c95966602cf 100644
--- 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
@@ -3,7 +3,6 @@
<%= 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 %>
@@ -12,5 +11,11 @@
<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;
+
+ <% if @review.planned? %>
+ &nbsp;
+ <%= submit_to_remote "submit_btn", message('reviews.unlink_action_plan_submit'), :url => {:action => 'unlink_from_action_plan'}, :html => {:id => "submit_btn"}, :update => 'review' -%>
+ <% end %>
+
<%= 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 6b2ef05584f..c14286d71f9 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
@@ -39,10 +39,14 @@
:update => "actionForm",
:complete => "$('actionButtons').remove();$('actionForm').show();$('selectSeverity').focus();" -%>
- <%= button_to_remote message('reviews.link_to_action_plan'),
+ <% if ActionPlan.open_by_project_id(@review.project_id).size>0 %>
+ <%= 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();" -%>
+ <% else %>
+ <input type="button" value="<%= message('reviews.link_to_action_plan') -%>" onclick="alert('<%= message('reviews.an_action_plan_must_be_created_first') -%>');">
+ <% end %>
<% end %>
</div>
<% end %>
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
index 596ca7b9611..6ce542a8d7d 100644
--- 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
@@ -3,7 +3,6 @@
<%= 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 %>
@@ -22,6 +21,12 @@
</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] -%>
+
+ <% if @violation.review && @violation.review.planned? %>
+ &nbsp;
+ <%= submit_to_remote "submit_btn"+params[:id], message('reviews.unlink_action_plan_submit'), :url => {:action => 'violation_unlink_from_action_plan'}, :html => {:id => "submit_btn"+params[:id]}, :update => 'vId'+params[:id] -%>
+ <% end %>
+
&nbsp;
<%= link_to_function message('cancel'), "cancelViolationAction(#{params[:id]})" -%>
</form>