Adds a workflow overview screen.

Workflow setup moved to a dedicated controller.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1914 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2008-09-28 12:03:17 +00:00
parent 85711f1d54
commit a37af7a226
9 changed files with 208 additions and 65 deletions

View File

@ -79,27 +79,6 @@ class RolesController < ApplicationController
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? }

View File

@ -0,0 +1,45 @@
# 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

View File

@ -0,0 +1,19 @@
# 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

View File

@ -21,4 +21,23 @@ class Workflow < ActiveRecord::Base
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

View File

@ -19,7 +19,7 @@
<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">

View File

@ -1,8 +1,12 @@
<div class="contextual">
<%= link_to l(:field_summary), :action => 'index' %>
</div>
<h2><%=l(:label_workflow)%></h2>
<p><%=l(:text_workflow_edit)%>:</p>
<% form_tag({:action => 'workflow'}, :method => 'get') do %>
<% 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?) %>
@ -12,14 +16,16 @@
<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) %>
<%= submit_tag l(:button_edit), :name => nil %>
</p>
<% end %>
<% unless @tracker.nil? or @role.nil? %>
<% form_tag({:action => 'workflow', :role_id => @role, :tracker_id => @tracker }, :id => 'workflow_form' ) do %>
<% 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>

View File

@ -0,0 +1,31 @@
<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 %>

View File

@ -118,46 +118,6 @@ class RolesControllerTest < Test::Unit::TestCase
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

View File

@ -0,0 +1,84 @@
# 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&amp;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