Allow additional workflow transitions for issue author and assignee (#2732).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4895 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
1 parent
7ddb1c694a
commit
4b096e9a56
11 files changed
+221
-83
No files matched your search
@@ -32,14 +32,17 @@ class WorkflowsController < ApplicationController
|
||||
|
||||
if request.post?
|
||||
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
|
||||
(params[:issue_status] || []).each { |old, news|
|
||||
news.each { |new|
|
||||
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
|
||||
(params[:issue_status] || []).each { |status_id, transitions|
|
||||
transitions.each { |new_status_id, options|
|
||||
author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
|
||||
assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
|
||||
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
|
||||
}
|
||||
}
|
||||
if @role.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,6 +51,14 @@ class WorkflowsController < ApplicationController
|
||||
@statuses = @tracker.issue_statuses
|
||||
end
|
||||
@statuses ||= IssueStatus.find(:all, :order => 'position')
|
||||
|
||||
if @tracker && @role && @statuses.any?
|
||||
workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id})
|
||||
@workflows = {}
|
||||
@workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
|
||||
@workflows['author'] = workflows.select {|w| w.author}
|
||||
@workflows['assignee'] = workflows.select {|w| w.assignee}
|
||||
end
|
||||
end
|
||||
|
||||
def copy
|
||||
|
||||
+6
-1
@@ -422,7 +422,12 @@ class Issue < ActiveRecord::Base
|
||||
|
||||
# Returns an array of status that user is able to apply
|
||||
def new_statuses_allowed_to(user, include_default=false)
|
||||
statuses = status.find_new_statuses_allowed_to(user.roles_for_project(project), tracker)
|
||||
statuses = status.find_new_statuses_allowed_to(
|
||||
user.roles_for_project(project),
|
||||
tracker,
|
||||
author == user,
|
||||
assigned_to_id_changed? ? assigned_to_id_was == user.id : assigned_to_id == user.id
|
||||
)
|
||||
statuses << status unless statuses.empty?
|
||||
statuses << IssueStatus.default if include_default
|
||||
statuses = statuses.uniq.sort
|
||||
|
||||
+14
-13
@@ -50,10 +50,16 @@ class IssueStatus < ActiveRecord::Base
|
||||
|
||||
# Returns an array of all statuses the given role can switch to
|
||||
# Uses association cache when called more than one time
|
||||
def new_statuses_allowed_to(roles, tracker)
|
||||
def new_statuses_allowed_to(roles, tracker, author=false, assignee=false)
|
||||
if roles && tracker
|
||||
role_ids = roles.collect(&:id)
|
||||
new_statuses = workflows.select {|w| role_ids.include?(w.role_id) && w.tracker_id == tracker.id}.collect{|w| w.new_status}.compact.sort
|
||||
transitions = workflows.select do |w|
|
||||
role_ids.include?(w.role_id) &&
|
||||
w.tracker_id == tracker.id &&
|
||||
(author || !w.author) &&
|
||||
(assignee || !w.assignee)
|
||||
end
|
||||
transitions.collect{|w| w.new_status}.compact.sort
|
||||
else
|
||||
[]
|
||||
end
|
||||
@@ -61,24 +67,19 @@ class IssueStatus < ActiveRecord::Base
|
||||
|
||||
# Same thing as above but uses a database query
|
||||
# More efficient than the previous method if called just once
|
||||
def find_new_statuses_allowed_to(roles, tracker)
|
||||
def find_new_statuses_allowed_to(roles, tracker, author=false, assignee=false)
|
||||
if roles && tracker
|
||||
conditions = {:role_id => roles.collect(&:id), :tracker_id => tracker.id}
|
||||
conditions[:author] = false unless author
|
||||
conditions[:assignee] = false unless assignee
|
||||
|
||||
workflows.find(:all,
|
||||
:include => :new_status,
|
||||
:conditions => { :role_id => roles.collect(&:id),
|
||||
:tracker_id => tracker.id}).collect{ |w| w.new_status }.compact.sort
|
||||
:conditions => conditions).collect{|w| w.new_status}.compact.sort
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def new_status_allowed_to?(status, roles, tracker)
|
||||
if status && roles && tracker
|
||||
!workflows.find(:first, :conditions => {:new_status_id => status.id, :role_id => roles.collect(&:id), :tracker_id => tracker.id}).nil?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def <=>(status)
|
||||
position <=> status.position
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<table class="list transitions-<%= name %>">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">
|
||||
<%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.transitions-#{name} input')",
|
||||
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %>
|
||||
<%=l(:label_current_status)%>
|
||||
</th>
|
||||
<th align="center" colspan="<%= @statuses.length %>"><%=l(:label_new_statuses_allowed)%></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<% for new_status in @statuses %>
|
||||
<td width="<%= 75 / @statuses.size %>%" align="center">
|
||||
<%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.transitions-#{name} input.new-status-#{new_status.id}')",
|
||||
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %>
|
||||
<%=h new_status.name %>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for old_status in @statuses %>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<td>
|
||||
<%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.transitions-#{name} input.old-status-#{old_status.id}')",
|
||||
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %>
|
||||
|
||||
<%=h old_status.name %>
|
||||
</td>
|
||||
<% for new_status in @statuses -%>
|
||||
<td align="center">
|
||||
<%= check_box_tag "issue_status[#{ old_status.id }][#{new_status.id}][]", name, workflows.detect {|w| w.old_status_id == old_status.id && w.new_status_id == new_status.id},
|
||||
:class => "old-status-#{old_status.id} new-status-#{new_status.id}" %>
|
||||
</td>
|
||||
<% end -%>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -20,54 +20,31 @@
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
|
||||
<% if @tracker && @role && @statuses.any? %>
|
||||
<% form_tag({}, :id => 'workflow_form' ) do %>
|
||||
<%= hidden_field_tag 'tracker_id', @tracker.id %>
|
||||
<%= hidden_field_tag 'role_id', @role.id %>
|
||||
<div class="autoscroll">
|
||||
<table class="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left"><%=l(:label_current_status)%></th>
|
||||
<th align="center" colspan="<%= @statuses.length %>"><%=l(:label_new_statuses_allowed)%></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<% for new_status in @statuses %>
|
||||
<td width="<%= 75 / @statuses.size %>%" align="center">
|
||||
<%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('input.new-status-#{new_status.id}')",
|
||||
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %>
|
||||
<%= new_status.name %>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for old_status in @statuses %>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<td>
|
||||
<%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('input.old-status-#{old_status.id}')",
|
||||
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %>
|
||||
|
||||
<%= old_status.name %>
|
||||
</td>
|
||||
<% new_status_ids_allowed = old_status.find_new_statuses_allowed_to([@role], @tracker).collect(&:id) -%>
|
||||
<% for new_status in @statuses -%>
|
||||
<td align="center">
|
||||
<%= check_box_tag "issue_status[#{ old_status.id }][]", new_status.id, new_status_ids_allowed.include?(new_status.id),
|
||||
:class => "old-status-#{old_status.id} new-status-#{new_status.id}" %>
|
||||
</td>
|
||||
<% end -%>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p><%= check_all_links 'workflow_form' %></p>
|
||||
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
||||
<% form_tag({}, :id => 'workflow_form' ) do %>
|
||||
<%= hidden_field_tag 'tracker_id', @tracker.id %>
|
||||
<%= hidden_field_tag 'role_id', @role.id %>
|
||||
<div class="autoscroll">
|
||||
<%= render :partial => 'form', :locals => {:name => 'always', :workflows => @workflows['always']} %>
|
||||
|
||||
<fieldset class="collapsible" style="padding: 0; margin-top: 0.5em;">
|
||||
<legend onclick="toggleFieldset(this);">Autorisations supplémentaires lorsque l'utilisateur a créé la demande</legend>
|
||||
<div id="author_workflows" style="margin: 0.5em 0 0.5em 0;">
|
||||
<%= render :partial => 'form', :locals => {:name => 'author', :workflows => @workflows['author']} %>
|
||||
</div>
|
||||
</fieldset>
|
||||
<%= javascript_tag "hideFieldset($('author_workflows'))" unless @workflows['author'].present? %>
|
||||
|
||||
<fieldset class="collapsible" style="padding: 0;">
|
||||
<legend onclick="toggleFieldset(this);">Autorisations supplémentaires lorsque la demande est assignée à l'utilisateur</legend>
|
||||
<div id="assignee_workflows" style="margin: 0.5em 0 0.5em 0;">
|
||||
<%= render :partial => 'form', :locals => {:name => 'assignee', :workflows => @workflows['assignee']} %>
|
||||
</div>
|
||||
</fieldset>
|
||||
<%= javascript_tag "hideFieldset($('assignee_workflows'))" unless @workflows['assignee'].present? %>
|
||||
</div>
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% html_title(l(:label_workflow)) -%>
|
||||
Reference in new issue
Block a user