OSDN Git Service

Adds a workflow overview screen.
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 28 Sep 2008 12:03:17 +0000 (12:03 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 28 Sep 2008 12:03:17 +0000 (12:03 +0000)
Workflow setup moved to a dedicated controller.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1914 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/roles_controller.rb
app/controllers/workflows_controller.rb [new file with mode: 0644]
app/helpers/workflows_helper.rb [new file with mode: 0644]
app/models/workflow.rb
app/views/admin/index.rhtml
app/views/workflows/edit.rhtml [moved from app/views/roles/workflow.rhtml with 83% similarity]
app/views/workflows/index.rhtml [new file with mode: 0644]
test/functional/roles_controller_test.rb
test/functional/workflows_controller_test.rb [new file with mode: 0644]

index 72555e5..ab70ebf 100644 (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? }
diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb
new file mode 100644 (file)
index 0000000..380d4e7
--- /dev/null
@@ -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
diff --git a/app/helpers/workflows_helper.rb b/app/helpers/workflows_helper.rb
new file mode 100644 (file)
index 0000000..48ded30
--- /dev/null
@@ -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
index 89322aa..e254ac4 100644 (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
index 18bee34..438f72a 100644 (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">
similarity index 83%
rename from app/views/roles/workflow.rhtml
rename to app/views/workflows/edit.rhtml
index 0f08b0d..00d6115 100644 (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?) %>
 <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>
diff --git a/app/views/workflows/index.rhtml b/app/views/workflows/index.rhtml
new file mode 100644 (file)
index 0000000..2fd080d
--- /dev/null
@@ -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 %>
index d70a4f0..188e79e 100644 (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
diff --git a/test/functional/workflows_controller_test.rb b/test/functional/workflows_controller_test.rb
new file mode 100644 (file)
index 0000000..8630f63
--- /dev/null
@@ -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