redirect_to :action => 'list'
end
- def workflow
- @role = Role.find_by_id(params[:role_id])
- @tracker = Tracker.find_by_id(params[:tracker_id])
-
- 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)
- }
- }
- if @role.save
- flash[:notice] = l(:notice_successful_update)
- redirect_to :action => 'workflow', :role_id => @role, :tracker_id => @tracker
- end
- end
- @roles = Role.find(:all, :order => 'builtin, position')
- @trackers = Tracker.find(:all, :order => 'position')
- @statuses = IssueStatus.find(:all, :order => 'position')
- end
-
def report
@roles = Role.find(:all, :order => 'builtin, position')
@permissions = Redmine::AccessControl.permissions.select { |p| !p.public? }
--- /dev/null
+# Redmine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class WorkflowsController < ApplicationController
+ before_filter :require_admin
+
+ def index
+ @workflow_counts = Workflow.count_by_tracker_and_role
+ end
+
+ def edit
+ @role = Role.find_by_id(params[:role_id])
+ @tracker = Tracker.find_by_id(params[:tracker_id])
+
+ 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)
+ }
+ }
+ if @role.save
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker
+ end
+ end
+ @roles = Role.find(:all, :order => 'builtin, position')
+ @trackers = Tracker.find(:all, :order => 'position')
+ @statuses = IssueStatus.find(:all, :order => 'position')
+ end
+end
--- /dev/null
+# Redmine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module WorkflowsHelper
+end
belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
validates_presence_of :role, :old_status, :new_status
+
+ # Returns workflow transitions count by tracker and role
+ def self.count_by_tracker_and_role
+ counts = connection.select_all("SELECT role_id, tracker_id, count(id) AS c FROM #{Workflow.table_name} GROUP BY role_id, tracker_id")
+ roles = Role.find(:all, :order => 'builtin, position')
+ trackers = Tracker.find(:all, :order => 'position')
+
+ result = []
+ trackers.each do |tracker|
+ t = []
+ roles.each do |role|
+ row = counts.detect {|c| c['role_id'] == role.id.to_s && c['tracker_id'] = tracker.id.to_s}
+ t << [role, (row.nil? ? 0 : row['c'].to_i)]
+ end
+ result << [tracker, t]
+ end
+
+ result
+ end
end
<p class="icon22 icon22-tracker">
<%= link_to l(:label_tracker_plural), :controller => 'trackers' %> |
<%= link_to l(:label_issue_status_plural), :controller => 'issue_statuses' %> |
-<%= link_to l(:label_workflow), :controller => 'roles', :action => 'workflow' %>
+<%= link_to l(:label_workflow), :controller => 'workflows', :action => 'edit' %>
</p>
<p class="icon22 icon22-workflow">
+++ /dev/null
-<h2><%=l(:label_workflow)%></h2>
-
-<p><%=l(:text_workflow_edit)%>:</p>
-
-<% form_tag({:action => 'workflow'}, :method => 'get') do %>
-<p><label for="role_id"><%=l(:label_role)%>:</label>
-<select id="role_id" name="role_id">
- <%= options_from_collection_for_select @roles, "id", "name", (@role.id unless @role.nil?) %>
-</select>
-
-<label for="tracker_id"><%=l(:label_tracker)%>:</label>
-<select id="tracker_id" name="tracker_id">
- <%= options_from_collection_for_select @trackers, "id", "name", (@tracker.id unless @tracker.nil?) %>
-</select>
-<%= submit_tag l(:button_edit) %>
-</p>
-<% end %>
-
-
-
-<% unless @tracker.nil? or @role.nil? %>
-<% form_tag({:action => 'workflow', :role_id => @role, :tracker_id => @tracker }, :id => 'workflow_form' ) do %>
-<div class="box">
- <table>
- <tr>
- <td align="center"><strong><%=l(:label_current_status)%></strong></td>
- <td align="center" colspan="<%= @statuses.length %>"><strong><%=l(:label_new_statuses_allowed)%></strong></td>
- </tr>
- <tr>
- <td></td>
- <% for new_status in @statuses %>
- <td width="80" align="center"><%= new_status.name %></td>
- <% end %>
- </tr>
-
- <% for old_status in @statuses %>
- <tr>
- <td><%= 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">
- <input type="checkbox"
- name="issue_status[<%= old_status.id %>][]"
- value="<%= new_status.id %>"
- <%= 'checked="checked"' if new_status_ids_allowed.include? new_status.id %>>
- </td>
- <% end -%>
- </tr>
- <% end %>
- </table>
- <p><%= check_all_links 'workflow_form' %></p>
-</div>
-<%= submit_tag l(:button_save) %>
-<% end %>
-
-<% end %>
-
-<% html_title(l(:label_workflow)) -%>
--- /dev/null
+<div class="contextual">
+<%= link_to l(:field_summary), :action => 'index' %>
+</div>
+
+<h2><%=l(:label_workflow)%></h2>
+
+<p><%=l(:text_workflow_edit)%>:</p>
+
+<% form_tag({}, :method => 'get') do %>
+<p><label for="role_id"><%=l(:label_role)%>:</label>
+<select id="role_id" name="role_id">
+ <%= options_from_collection_for_select @roles, "id", "name", (@role.id unless @role.nil?) %>
+</select>
+
+<label for="tracker_id"><%=l(:label_tracker)%>:</label>
+<select id="tracker_id" name="tracker_id">
+ <%= options_from_collection_for_select @trackers, "id", "name", (@tracker.id unless @tracker.nil?) %>
+</select>
+<%= submit_tag l(:button_edit), :name => nil %>
+</p>
+<% end %>
+
+
+
+<% unless @tracker.nil? or @role.nil? %>
+<% form_tag({}, :id => 'workflow_form' ) do %>
+<%= hidden_field_tag 'tracker_id', @tracker.id %>
+<%= hidden_field_tag 'role_id', @role.id %>
+<div class="box">
+ <table>
+ <tr>
+ <td align="center"><strong><%=l(:label_current_status)%></strong></td>
+ <td align="center" colspan="<%= @statuses.length %>"><strong><%=l(:label_new_statuses_allowed)%></strong></td>
+ </tr>
+ <tr>
+ <td></td>
+ <% for new_status in @statuses %>
+ <td width="80" align="center"><%= new_status.name %></td>
+ <% end %>
+ </tr>
+
+ <% for old_status in @statuses %>
+ <tr>
+ <td><%= 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">
+ <input type="checkbox"
+ name="issue_status[<%= old_status.id %>][]"
+ value="<%= new_status.id %>"
+ <%= 'checked="checked"' if new_status_ids_allowed.include? new_status.id %>>
+ </td>
+ <% end -%>
+ </tr>
+ <% end %>
+ </table>
+ <p><%= check_all_links 'workflow_form' %></p>
+</div>
+<%= submit_tag l(:button_save) %>
+<% end %>
+
+<% end %>
+
+<% html_title(l(:label_workflow)) -%>
--- /dev/null
+<h2><%=l(:label_workflow)%></h2>
+
+<% if @workflow_counts.empty? %>
+<p class="nodata"><%= l(:label_no_data) %></p>
+<% else %>
+<table class="list">
+<thead>
+ <tr>
+ <th></th>
+ <% @workflow_counts.first.last.each do |role, count| %>
+ <th>
+ <%= content_tag(role.builtin? ? 'em' : 'span', h(role.name)) %>
+ </th>
+
+ <% end %>
+ </tr>
+</thead>
+<tbody>
+<% @workflow_counts.each do |tracker, roles| -%>
+<tr class="<%= cycle('odd', 'even') %>">
+ <td><%= h tracker %></td>
+ <% roles.each do |role, count| -%>
+ <td align="center">
+ <%= link_to((count > 1 ? count : image_tag('false.png')), {:action => 'edit', :role_id => role, :tracker_id => tracker}, :title => l(:button_edit)) %>
+ </td>
+ <% end -%>
+</tr>
+<% end -%>
+</tbody>
+</table>
+<% end %>
assert_not_nil Role.find_by_id(1)
end
- def test_get_workflow
- get :workflow
- assert_response :success
- assert_template 'workflow'
- assert_not_nil assigns(:roles)
- assert_not_nil assigns(:trackers)
- end
-
- def test_get_workflow_with_role_and_tracker
- get :workflow, :role_id => 2, :tracker_id => 1
- assert_response :success
- assert_template 'workflow'
- # allowed transitions
- assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
- :name => 'issue_status[2][]',
- :value => '1',
- :checked => 'checked' }
- # not allowed
- assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
- :name => 'issue_status[2][]',
- :value => '3',
- :checked => nil }
- end
-
- def test_post_workflow
- post :workflow, :role_id => 2, :tracker_id => 1, :issue_status => {'4' => ['5'], '3' => ['1', '2']}
- assert_redirected_to 'roles/workflow'
-
- assert_equal 3, Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2})
- assert_not_nil Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2})
- assert_nil Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4})
- end
-
- def test_clear_workflow
- assert Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2}) > 0
-
- post :workflow, :role_id => 2, :tracker_id => 1
- assert_equal 0, Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2})
- end
-
def test_get_report
get :report
assert_response :success
--- /dev/null
+# Redmine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require File.dirname(__FILE__) + '/../test_helper'
+require 'workflows_controller'
+
+# Re-raise errors caught by the controller.
+class WorkflowsController; def rescue_action(e) raise e end; end
+
+class WorkflowsControllerTest < Test::Unit::TestCase
+ fixtures :roles, :trackers, :workflows
+
+ def setup
+ @controller = WorkflowsController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ User.current = nil
+ @request.session[:user_id] = 1 # admin
+ end
+
+ def test_index
+ get :index
+ assert_response :success
+ assert_template 'index'
+
+ count = Workflow.count(:all, :conditions => 'role_id = 1 AND tracker_id = 2')
+ assert_tag :tag => 'a', :content => count.to_s,
+ :attributes => { :href => '/workflows/edit?role_id=1&tracker_id=2' }
+ end
+
+ def test_get_edit
+ get :edit
+ assert_response :success
+ assert_template 'edit'
+ assert_not_nil assigns(:roles)
+ assert_not_nil assigns(:trackers)
+ end
+
+ def test_get_edit_with_role_and_tracker
+ get :edit, :role_id => 2, :tracker_id => 1
+ assert_response :success
+ assert_template 'edit'
+ # allowed transitions
+ assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
+ :name => 'issue_status[2][]',
+ :value => '1',
+ :checked => 'checked' }
+ # not allowed
+ assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
+ :name => 'issue_status[2][]',
+ :value => '3',
+ :checked => nil }
+ end
+
+ def test_post_edit
+ post :edit, :role_id => 2, :tracker_id => 1, :issue_status => {'4' => ['5'], '3' => ['1', '2']}
+ assert_redirected_to 'workflows/edit'
+
+ assert_equal 3, Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2})
+ assert_not_nil Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2})
+ assert_nil Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4})
+ end
+
+ def test_clear_workflow
+ assert Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2}) > 0
+
+ post :edit, :role_id => 2, :tracker_id => 1
+ assert_equal 0, Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2})
+ end
+end