##// END OF EJS Templates
Don't show roles without issue add/edit permission in workflow setup (#15988)....
Jean-Philippe Lang -
r13366:c886ffe200a4
parent child
Show More
@@ -1,140 +1,140
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class WorkflowsController < ApplicationController
18 class WorkflowsController < ApplicationController
19 layout 'admin'
19 layout 'admin'
20
20
21 before_filter :require_admin
21 before_filter :require_admin
22
22
23 def index
23 def index
24 @workflow_counts = WorkflowTransition.count_by_tracker_and_role
24 @workflow_counts = WorkflowTransition.count_by_tracker_and_role
25 end
25 end
26
26
27 def edit
27 def edit
28 find_trackers_roles_and_statuses_for_edit
28 find_trackers_roles_and_statuses_for_edit
29
29
30 if request.post? && @roles && @trackers && params[:transitions]
30 if request.post? && @roles && @trackers && params[:transitions]
31 transitions = params[:transitions].deep_dup
31 transitions = params[:transitions].deep_dup
32 transitions.each do |old_status_id, transitions_by_new_status|
32 transitions.each do |old_status_id, transitions_by_new_status|
33 transitions_by_new_status.each do |new_status_id, transition_by_rule|
33 transitions_by_new_status.each do |new_status_id, transition_by_rule|
34 transition_by_rule.reject! {|rule, transition| transition == 'no_change'}
34 transition_by_rule.reject! {|rule, transition| transition == 'no_change'}
35 end
35 end
36 end
36 end
37 WorkflowTransition.replace_transitions(@trackers, @roles, transitions)
37 WorkflowTransition.replace_transitions(@trackers, @roles, transitions)
38 flash[:notice] = l(:notice_successful_update)
38 flash[:notice] = l(:notice_successful_update)
39 redirect_to_referer_or workflows_edit_path
39 redirect_to_referer_or workflows_edit_path
40 return
40 return
41 end
41 end
42
42
43 if @trackers && @roles && @statuses.any?
43 if @trackers && @roles && @statuses.any?
44 workflows = WorkflowTransition.where(:role_id => @roles.map(&:id), :tracker_id => @trackers.map(&:id))
44 workflows = WorkflowTransition.where(:role_id => @roles.map(&:id), :tracker_id => @trackers.map(&:id))
45 @workflows = {}
45 @workflows = {}
46 @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
46 @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
47 @workflows['author'] = workflows.select {|w| w.author}
47 @workflows['author'] = workflows.select {|w| w.author}
48 @workflows['assignee'] = workflows.select {|w| w.assignee}
48 @workflows['assignee'] = workflows.select {|w| w.assignee}
49 end
49 end
50 end
50 end
51
51
52 def permissions
52 def permissions
53 find_trackers_roles_and_statuses_for_edit
53 find_trackers_roles_and_statuses_for_edit
54
54
55 if request.post? && @roles && @trackers && params[:permissions]
55 if request.post? && @roles && @trackers && params[:permissions]
56 permissions = params[:permissions].deep_dup
56 permissions = params[:permissions].deep_dup
57 permissions.each { |field, rule_by_status_id|
57 permissions.each { |field, rule_by_status_id|
58 rule_by_status_id.reject! {|status_id, rule| rule == 'no_change'}
58 rule_by_status_id.reject! {|status_id, rule| rule == 'no_change'}
59 }
59 }
60 WorkflowPermission.replace_permissions(@trackers, @roles, permissions)
60 WorkflowPermission.replace_permissions(@trackers, @roles, permissions)
61 flash[:notice] = l(:notice_successful_update)
61 flash[:notice] = l(:notice_successful_update)
62 redirect_to_referer_or workflows_permissions_path
62 redirect_to_referer_or workflows_permissions_path
63 return
63 return
64 end
64 end
65
65
66 if @roles && @trackers
66 if @roles && @trackers
67 @fields = (Tracker::CORE_FIELDS_ALL - @trackers.map(&:disabled_core_fields).reduce(:&)).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
67 @fields = (Tracker::CORE_FIELDS_ALL - @trackers.map(&:disabled_core_fields).reduce(:&)).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
68 @custom_fields = @trackers.map(&:custom_fields).flatten.uniq.sort
68 @custom_fields = @trackers.map(&:custom_fields).flatten.uniq.sort
69 @permissions = WorkflowPermission.rules_by_status_id(@trackers, @roles)
69 @permissions = WorkflowPermission.rules_by_status_id(@trackers, @roles)
70 @statuses.each {|status| @permissions[status.id] ||= {}}
70 @statuses.each {|status| @permissions[status.id] ||= {}}
71 end
71 end
72 end
72 end
73
73
74 def copy
74 def copy
75 @roles = Role.sorted
75 @roles = Role.sorted.select(&:consider_workflow?)
76 @trackers = Tracker.sorted
76 @trackers = Tracker.sorted
77
77
78 if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
78 if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
79 @source_tracker = nil
79 @source_tracker = nil
80 else
80 else
81 @source_tracker = Tracker.find_by_id(params[:source_tracker_id].to_i)
81 @source_tracker = Tracker.find_by_id(params[:source_tracker_id].to_i)
82 end
82 end
83 if params[:source_role_id].blank? || params[:source_role_id] == 'any'
83 if params[:source_role_id].blank? || params[:source_role_id] == 'any'
84 @source_role = nil
84 @source_role = nil
85 else
85 else
86 @source_role = Role.find_by_id(params[:source_role_id].to_i)
86 @source_role = Role.find_by_id(params[:source_role_id].to_i)
87 end
87 end
88 @target_trackers = params[:target_tracker_ids].blank? ?
88 @target_trackers = params[:target_tracker_ids].blank? ?
89 nil : Tracker.where(:id => params[:target_tracker_ids]).to_a
89 nil : Tracker.where(:id => params[:target_tracker_ids]).to_a
90 @target_roles = params[:target_role_ids].blank? ?
90 @target_roles = params[:target_role_ids].blank? ?
91 nil : Role.where(:id => params[:target_role_ids]).to_a
91 nil : Role.where(:id => params[:target_role_ids]).to_a
92 if request.post?
92 if request.post?
93 if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
93 if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
94 flash.now[:error] = l(:error_workflow_copy_source)
94 flash.now[:error] = l(:error_workflow_copy_source)
95 elsif @target_trackers.blank? || @target_roles.blank?
95 elsif @target_trackers.blank? || @target_roles.blank?
96 flash.now[:error] = l(:error_workflow_copy_target)
96 flash.now[:error] = l(:error_workflow_copy_target)
97 else
97 else
98 WorkflowRule.copy(@source_tracker, @source_role, @target_trackers, @target_roles)
98 WorkflowRule.copy(@source_tracker, @source_role, @target_trackers, @target_roles)
99 flash[:notice] = l(:notice_successful_update)
99 flash[:notice] = l(:notice_successful_update)
100 redirect_to workflows_copy_path(:source_tracker_id => @source_tracker, :source_role_id => @source_role)
100 redirect_to workflows_copy_path(:source_tracker_id => @source_tracker, :source_role_id => @source_role)
101 end
101 end
102 end
102 end
103 end
103 end
104
104
105 private
105 private
106
106
107 def find_trackers_roles_and_statuses_for_edit
107 def find_trackers_roles_and_statuses_for_edit
108 find_roles
108 find_roles
109 find_trackers
109 find_trackers
110 find_statuses
110 find_statuses
111 end
111 end
112
112
113 def find_roles
113 def find_roles
114 ids = Array.wrap(params[:role_id])
114 ids = Array.wrap(params[:role_id])
115 if ids == ['all']
115 if ids == ['all']
116 @roles = Role.sorted.to_a
116 @roles = Role.sorted.to_a
117 elsif ids.present?
117 elsif ids.present?
118 @roles = Role.where(:id => ids).to_a
118 @roles = Role.where(:id => ids).to_a
119 end
119 end
120 @roles = nil if @roles.blank?
120 @roles = nil if @roles.blank?
121 end
121 end
122
122
123 def find_trackers
123 def find_trackers
124 ids = Array.wrap(params[:tracker_id])
124 ids = Array.wrap(params[:tracker_id])
125 if ids == ['all']
125 if ids == ['all']
126 @trackers = Tracker.sorted.to_a
126 @trackers = Tracker.sorted.to_a
127 elsif ids.present?
127 elsif ids.present?
128 @trackers = Tracker.where(:id => ids).to_a
128 @trackers = Tracker.where(:id => ids).to_a
129 end
129 end
130 @trackers = nil if @trackers.blank?
130 @trackers = nil if @trackers.blank?
131 end
131 end
132
132
133 def find_statuses
133 def find_statuses
134 @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
134 @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
135 if @trackers && @used_statuses_only
135 if @trackers && @used_statuses_only
136 @statuses = @trackers.map(&:issue_statuses).flatten.uniq.sort.presence
136 @statuses = @trackers.map(&:issue_statuses).flatten.uniq.sort.presence
137 end
137 end
138 @statuses ||= IssueStatus.sorted.to_a
138 @statuses ||= IssueStatus.sorted.to_a
139 end
139 end
140 end
140 end
@@ -1,74 +1,74
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class WorkflowRule < ActiveRecord::Base
18 class WorkflowRule < ActiveRecord::Base
19 self.table_name = "#{table_name_prefix}workflows#{table_name_suffix}"
19 self.table_name = "#{table_name_prefix}workflows#{table_name_suffix}"
20
20
21 belongs_to :role
21 belongs_to :role
22 belongs_to :tracker
22 belongs_to :tracker
23 belongs_to :old_status, :class_name => 'IssueStatus'
23 belongs_to :old_status, :class_name => 'IssueStatus'
24 belongs_to :new_status, :class_name => 'IssueStatus'
24 belongs_to :new_status, :class_name => 'IssueStatus'
25
25
26 validates_presence_of :role, :tracker, :old_status
26 validates_presence_of :role, :tracker, :old_status
27 attr_protected :id
27 attr_protected :id
28
28
29 # Copies workflows from source to targets
29 # Copies workflows from source to targets
30 def self.copy(source_tracker, source_role, target_trackers, target_roles)
30 def self.copy(source_tracker, source_role, target_trackers, target_roles)
31 unless source_tracker.is_a?(Tracker) || source_role.is_a?(Role)
31 unless source_tracker.is_a?(Tracker) || source_role.is_a?(Role)
32 raise ArgumentError.new("source_tracker or source_role must be specified")
32 raise ArgumentError.new("source_tracker or source_role must be specified")
33 end
33 end
34
34
35 target_trackers = [target_trackers].flatten.compact
35 target_trackers = [target_trackers].flatten.compact
36 target_roles = [target_roles].flatten.compact
36 target_roles = [target_roles].flatten.compact
37
37
38 target_trackers = Tracker.sorted.to_a if target_trackers.empty?
38 target_trackers = Tracker.sorted.to_a if target_trackers.empty?
39 target_roles = Role.all if target_roles.empty?
39 target_roles = Role.all.select(&:consider_workflow?) if target_roles.empty?
40
40
41 target_trackers.each do |target_tracker|
41 target_trackers.each do |target_tracker|
42 target_roles.each do |target_role|
42 target_roles.each do |target_role|
43 copy_one(source_tracker || target_tracker,
43 copy_one(source_tracker || target_tracker,
44 source_role || target_role,
44 source_role || target_role,
45 target_tracker,
45 target_tracker,
46 target_role)
46 target_role)
47 end
47 end
48 end
48 end
49 end
49 end
50
50
51 # Copies a single set of workflows from source to target
51 # Copies a single set of workflows from source to target
52 def self.copy_one(source_tracker, source_role, target_tracker, target_role)
52 def self.copy_one(source_tracker, source_role, target_tracker, target_role)
53 unless source_tracker.is_a?(Tracker) && !source_tracker.new_record? &&
53 unless source_tracker.is_a?(Tracker) && !source_tracker.new_record? &&
54 source_role.is_a?(Role) && !source_role.new_record? &&
54 source_role.is_a?(Role) && !source_role.new_record? &&
55 target_tracker.is_a?(Tracker) && !target_tracker.new_record? &&
55 target_tracker.is_a?(Tracker) && !target_tracker.new_record? &&
56 target_role.is_a?(Role) && !target_role.new_record?
56 target_role.is_a?(Role) && !target_role.new_record?
57
57
58 raise ArgumentError.new("arguments can not be nil or unsaved objects")
58 raise ArgumentError.new("arguments can not be nil or unsaved objects")
59 end
59 end
60
60
61 if source_tracker == target_tracker && source_role == target_role
61 if source_tracker == target_tracker && source_role == target_role
62 false
62 false
63 else
63 else
64 transaction do
64 transaction do
65 delete_all :tracker_id => target_tracker.id, :role_id => target_role.id
65 delete_all :tracker_id => target_tracker.id, :role_id => target_role.id
66 connection.insert "INSERT INTO #{WorkflowRule.table_name} (tracker_id, role_id, old_status_id, new_status_id, author, assignee, field_name, #{connection.quote_column_name 'rule'}, type)" +
66 connection.insert "INSERT INTO #{WorkflowRule.table_name} (tracker_id, role_id, old_status_id, new_status_id, author, assignee, field_name, #{connection.quote_column_name 'rule'}, type)" +
67 " SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id, author, assignee, field_name, #{connection.quote_column_name 'rule'}, type" +
67 " SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id, author, assignee, field_name, #{connection.quote_column_name 'rule'}, type" +
68 " FROM #{WorkflowRule.table_name}" +
68 " FROM #{WorkflowRule.table_name}" +
69 " WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}"
69 " WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}"
70 end
70 end
71 true
71 true
72 end
72 end
73 end
73 end
74 end
74 end
@@ -1,102 +1,102
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class WorkflowTransition < WorkflowRule
18 class WorkflowTransition < WorkflowRule
19 validates_presence_of :new_status
19 validates_presence_of :new_status
20
20
21 # Returns workflow transitions count by tracker and role
21 # Returns workflow transitions count by tracker and role
22 def self.count_by_tracker_and_role
22 def self.count_by_tracker_and_role
23 counts = connection.select_all("SELECT role_id, tracker_id, count(id) AS c FROM #{table_name} WHERE type = 'WorkflowTransition' GROUP BY role_id, tracker_id")
23 counts = connection.select_all("SELECT role_id, tracker_id, count(id) AS c FROM #{table_name} WHERE type = 'WorkflowTransition' GROUP BY role_id, tracker_id")
24 roles = Role.sorted
24 roles = Role.sorted.to_a.select(&:consider_workflow?)
25 trackers = Tracker.sorted
25 trackers = Tracker.sorted
26 result = []
26 result = []
27 trackers.each do |tracker|
27 trackers.each do |tracker|
28 t = []
28 t = []
29 roles.each do |role|
29 roles.each do |role|
30 row = counts.detect {|c| c['role_id'].to_s == role.id.to_s && c['tracker_id'].to_s == tracker.id.to_s}
30 row = counts.detect {|c| c['role_id'].to_s == role.id.to_s && c['tracker_id'].to_s == tracker.id.to_s}
31 t << [role, (row.nil? ? 0 : row['c'].to_i)]
31 t << [role, (row.nil? ? 0 : row['c'].to_i)]
32 end
32 end
33 result << [tracker, t]
33 result << [tracker, t]
34 end
34 end
35 result
35 result
36 end
36 end
37
37
38 def self.replace_transitions(trackers, roles, transitions)
38 def self.replace_transitions(trackers, roles, transitions)
39 trackers = Array.wrap trackers
39 trackers = Array.wrap trackers
40 roles = Array.wrap roles
40 roles = Array.wrap roles
41
41
42 transaction do
42 transaction do
43 records = WorkflowTransition.where(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id)).to_a
43 records = WorkflowTransition.where(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id)).to_a
44
44
45 transitions.each do |old_status_id, transitions_by_new_status|
45 transitions.each do |old_status_id, transitions_by_new_status|
46 transitions_by_new_status.each do |new_status_id, transition_by_rule|
46 transitions_by_new_status.each do |new_status_id, transition_by_rule|
47 transition_by_rule.each do |rule, transition|
47 transition_by_rule.each do |rule, transition|
48 trackers.each do |tracker|
48 trackers.each do |tracker|
49 roles.each do |role|
49 roles.each do |role|
50 w = records.select {|r|
50 w = records.select {|r|
51 r.old_status_id == old_status_id.to_i &&
51 r.old_status_id == old_status_id.to_i &&
52 r.new_status_id == new_status_id.to_i &&
52 r.new_status_id == new_status_id.to_i &&
53 r.tracker_id == tracker.id &&
53 r.tracker_id == tracker.id &&
54 r.role_id == role.id &&
54 r.role_id == role.id &&
55 !r.destroyed?
55 !r.destroyed?
56 }
56 }
57
57
58 if rule == 'always'
58 if rule == 'always'
59 w = w.select {|r| !r.author && !r.assignee}
59 w = w.select {|r| !r.author && !r.assignee}
60 else
60 else
61 w = w.select {|r| r.author || r.assignee}
61 w = w.select {|r| r.author || r.assignee}
62 end
62 end
63 if w.size > 1
63 if w.size > 1
64 w[1..-1].each(&:destroy)
64 w[1..-1].each(&:destroy)
65 end
65 end
66 w = w.first
66 w = w.first
67
67
68 if transition == "1" || transition == true
68 if transition == "1" || transition == true
69 unless w
69 unless w
70 w = WorkflowTransition.new(:old_status_id => old_status_id, :new_status_id => new_status_id, :tracker_id => tracker.id, :role_id => role.id)
70 w = WorkflowTransition.new(:old_status_id => old_status_id, :new_status_id => new_status_id, :tracker_id => tracker.id, :role_id => role.id)
71 records << w
71 records << w
72 end
72 end
73 w.author = true if rule == "author"
73 w.author = true if rule == "author"
74 w.assignee = true if rule == "assignee"
74 w.assignee = true if rule == "assignee"
75 w.save if w.changed?
75 w.save if w.changed?
76 elsif w
76 elsif w
77 if rule == 'always'
77 if rule == 'always'
78 w.destroy
78 w.destroy
79 elsif rule == 'author'
79 elsif rule == 'author'
80 if w.assignee
80 if w.assignee
81 w.author = false
81 w.author = false
82 w.save if w.changed?
82 w.save if w.changed?
83 else
83 else
84 w.destroy
84 w.destroy
85 end
85 end
86 elsif rule == 'assignee'
86 elsif rule == 'assignee'
87 if w.author
87 if w.author
88 w.assignee = false
88 w.assignee = false
89 w.save if w.changed?
89 w.save if w.changed?
90 else
90 else
91 w.destroy
91 w.destroy
92 end
92 end
93 end
93 end
94 end
94 end
95 end
95 end
96 end
96 end
97 end
97 end
98 end
98 end
99 end
99 end
100 end
100 end
101 end
101 end
102 end
102 end
@@ -1,75 +1,75
1 <%= render :partial => 'action_menu' %>
1 <%= render :partial => 'action_menu' %>
2
2
3 <%= title l(:label_workflow) %>
3 <%= title l(:label_workflow) %>
4
4
5 <div class="tabs">
5 <div class="tabs">
6 <ul>
6 <ul>
7 <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
7 <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
8 <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers) %></li>
8 <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers) %></li>
9 </ul>
9 </ul>
10 </div>
10 </div>
11
11
12 <p><%=l(:text_workflow_edit)%>:</p>
12 <p><%=l(:text_workflow_edit)%>:</p>
13
13
14 <%= form_tag({}, :method => 'get') do %>
14 <%= form_tag({}, :method => 'get') do %>
15 <p>
15 <p>
16 <label><%=l(:label_role)%>:
16 <label><%=l(:label_role)%>:
17 <%= options_for_workflow_select 'role_id[]', Role.sorted, @roles, :id => 'role_id', :class => 'expandable' %>
17 <%= options_for_workflow_select 'role_id[]', Role.sorted.select(&:consider_workflow?), @roles, :id => 'role_id', :class => 'expandable' %>
18 </label>
18 </label>
19 <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
19 <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
20
20
21 <label><%=l(:label_tracker)%>:
21 <label><%=l(:label_tracker)%>:
22 <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
22 <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
23 </label>
23 </label>
24 <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
24 <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
25
25
26 <%= submit_tag l(:button_edit), :name => nil %>
26 <%= submit_tag l(:button_edit), :name => nil %>
27
27
28 <%= hidden_field_tag 'used_statuses_only', '0', :id => nil %>
28 <%= hidden_field_tag 'used_statuses_only', '0', :id => nil %>
29 <label><%= check_box_tag 'used_statuses_only', '1', @used_statuses_only %> <%= l(:label_display_used_statuses_only) %></label>
29 <label><%= check_box_tag 'used_statuses_only', '1', @used_statuses_only %> <%= l(:label_display_used_statuses_only) %></label>
30
30
31 </p>
31 </p>
32 <% end %>
32 <% end %>
33
33
34 <% if @trackers && @roles && @statuses.any? %>
34 <% if @trackers && @roles && @statuses.any? %>
35 <%= form_tag({}, :id => 'workflow_form' ) do %>
35 <%= form_tag({}, :id => 'workflow_form' ) do %>
36 <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id, :id => nil}.join.html_safe %>
36 <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id, :id => nil}.join.html_safe %>
37 <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id, :id => nil}.join.html_safe %>
37 <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id, :id => nil}.join.html_safe %>
38 <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only], :id => nil %>
38 <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only], :id => nil %>
39 <div class="autoscroll">
39 <div class="autoscroll">
40 <%= render :partial => 'form', :locals => {:name => 'always', :workflows => @workflows['always']} %>
40 <%= render :partial => 'form', :locals => {:name => 'always', :workflows => @workflows['always']} %>
41
41
42 <fieldset class="collapsible" style="padding: 0; margin-top: 0.5em;">
42 <fieldset class="collapsible" style="padding: 0; margin-top: 0.5em;">
43 <legend onclick="toggleFieldset(this);"><%= l(:label_additional_workflow_transitions_for_author) %></legend>
43 <legend onclick="toggleFieldset(this);"><%= l(:label_additional_workflow_transitions_for_author) %></legend>
44 <div id="author_workflows" style="margin: 0.5em 0 0.5em 0;">
44 <div id="author_workflows" style="margin: 0.5em 0 0.5em 0;">
45 <%= render :partial => 'form', :locals => {:name => 'author', :workflows => @workflows['author']} %>
45 <%= render :partial => 'form', :locals => {:name => 'author', :workflows => @workflows['author']} %>
46 </div>
46 </div>
47 </fieldset>
47 </fieldset>
48 <%= javascript_tag "hideFieldset($('#author_workflows'))" unless @workflows['author'].present? %>
48 <%= javascript_tag "hideFieldset($('#author_workflows'))" unless @workflows['author'].present? %>
49
49
50 <fieldset class="collapsible" style="padding: 0;">
50 <fieldset class="collapsible" style="padding: 0;">
51 <legend onclick="toggleFieldset(this);"><%= l(:label_additional_workflow_transitions_for_assignee) %></legend>
51 <legend onclick="toggleFieldset(this);"><%= l(:label_additional_workflow_transitions_for_assignee) %></legend>
52 <div id="assignee_workflows" style="margin: 0.5em 0 0.5em 0;">
52 <div id="assignee_workflows" style="margin: 0.5em 0 0.5em 0;">
53 <%= render :partial => 'form', :locals => {:name => 'assignee', :workflows => @workflows['assignee']} %>
53 <%= render :partial => 'form', :locals => {:name => 'assignee', :workflows => @workflows['assignee']} %>
54 </div>
54 </div>
55 </fieldset>
55 </fieldset>
56 <%= javascript_tag "hideFieldset($('#assignee_workflows'))" unless @workflows['assignee'].present? %>
56 <%= javascript_tag "hideFieldset($('#assignee_workflows'))" unless @workflows['assignee'].present? %>
57 </div>
57 </div>
58 <%= submit_tag l(:button_save) %>
58 <%= submit_tag l(:button_save) %>
59 <% end %>
59 <% end %>
60 <% end %>
60 <% end %>
61
61
62 <%= javascript_tag do %>
62 <%= javascript_tag do %>
63 $("a[data-expands]").click(function(e){
63 $("a[data-expands]").click(function(e){
64 e.preventDefault();
64 e.preventDefault();
65 var target = $($(this).attr("data-expands"));
65 var target = $($(this).attr("data-expands"));
66 if (target.attr("multiple")) {
66 if (target.attr("multiple")) {
67 target.attr("multiple", false);
67 target.attr("multiple", false);
68 target.find("option[value=all]").show();
68 target.find("option[value=all]").show();
69 } else {
69 } else {
70 target.attr("multiple", true);
70 target.attr("multiple", true);
71 target.find("option[value=all]").attr("selected", false).hide();
71 target.find("option[value=all]").attr("selected", false).hide();
72 }
72 }
73 });
73 });
74
74
75 <% end %>
75 <% end %>
@@ -1,123 +1,123
1 <%= render :partial => 'action_menu' %>
1 <%= render :partial => 'action_menu' %>
2
2
3 <%= title l(:label_workflow) %>
3 <%= title l(:label_workflow) %>
4
4
5 <div class="tabs">
5 <div class="tabs">
6 <ul>
6 <ul>
7 <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers) %></li>
7 <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers) %></li>
8 <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
8 <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
9 </ul>
9 </ul>
10 </div>
10 </div>
11
11
12 <p><%=l(:text_workflow_edit)%>:</p>
12 <p><%=l(:text_workflow_edit)%>:</p>
13
13
14 <%= form_tag({}, :method => 'get') do %>
14 <%= form_tag({}, :method => 'get') do %>
15 <p>
15 <p>
16 <label><%=l(:label_role)%>:
16 <label><%=l(:label_role)%>:
17 <%= options_for_workflow_select 'role_id[]', Role.sorted, @roles, :id => 'role_id', :class => 'expandable' %>
17 <%= options_for_workflow_select 'role_id[]', Role.sorted.select(&:consider_workflow?), @roles, :id => 'role_id', :class => 'expandable' %>
18 </label>
18 </label>
19 <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
19 <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
20
20
21 <label><%=l(:label_tracker)%>:
21 <label><%=l(:label_tracker)%>:
22 <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
22 <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
23 </label>
23 </label>
24 <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
24 <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
25
25
26 <%= submit_tag l(:button_edit), :name => nil %>
26 <%= submit_tag l(:button_edit), :name => nil %>
27
27
28 <%= hidden_field_tag 'used_statuses_only', '0', :id => nil %>
28 <%= hidden_field_tag 'used_statuses_only', '0', :id => nil %>
29 <label><%= check_box_tag 'used_statuses_only', '1', @used_statuses_only %> <%= l(:label_display_used_statuses_only) %></label>
29 <label><%= check_box_tag 'used_statuses_only', '1', @used_statuses_only %> <%= l(:label_display_used_statuses_only) %></label>
30 </p>
30 </p>
31 <% end %>
31 <% end %>
32
32
33 <% if @trackers && @roles && @statuses.any? %>
33 <% if @trackers && @roles && @statuses.any? %>
34 <%= form_tag({}, :id => 'workflow_form' ) do %>
34 <%= form_tag({}, :id => 'workflow_form' ) do %>
35 <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id, :id => nil}.join.html_safe %>
35 <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id, :id => nil}.join.html_safe %>
36 <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id, :id => nil}.join.html_safe %>
36 <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id, :id => nil}.join.html_safe %>
37 <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only], :id => nil %>
37 <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only], :id => nil %>
38 <div class="autoscroll">
38 <div class="autoscroll">
39 <table class="list workflows fields_permissions">
39 <table class="list workflows fields_permissions">
40 <thead>
40 <thead>
41 <tr>
41 <tr>
42 <th>
42 <th>
43 </th>
43 </th>
44 <th colspan="<%= @statuses.length %>"><%=l(:label_issue_status)%></th>
44 <th colspan="<%= @statuses.length %>"><%=l(:label_issue_status)%></th>
45 </tr>
45 </tr>
46 <tr>
46 <tr>
47 <td></td>
47 <td></td>
48 <% for status in @statuses %>
48 <% for status in @statuses %>
49 <td style="width:<%= 75 / @statuses.size %>%;">
49 <td style="width:<%= 75 / @statuses.size %>%;">
50 <%=h status.name %>
50 <%=h status.name %>
51 </td>
51 </td>
52 <% end %>
52 <% end %>
53 </tr>
53 </tr>
54 </thead>
54 </thead>
55 <tbody>
55 <tbody>
56 <tr class="group open">
56 <tr class="group open">
57 <td colspan="<%= @statuses.size + 1 %>">
57 <td colspan="<%= @statuses.size + 1 %>">
58 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
58 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
59 <%= l(:field_core_fields) %>
59 <%= l(:field_core_fields) %>
60 </td>
60 </td>
61 </tr>
61 </tr>
62 <% @fields.each do |field, name| %>
62 <% @fields.each do |field, name| %>
63 <tr class="<%= cycle("odd", "even") %>">
63 <tr class="<%= cycle("odd", "even") %>">
64 <td class="name">
64 <td class="name">
65 <%=h name %> <%= content_tag('span', '*', :class => 'required') if field_required?(field) %>
65 <%=h name %> <%= content_tag('span', '*', :class => 'required') if field_required?(field) %>
66 </td>
66 </td>
67 <% for status in @statuses -%>
67 <% for status in @statuses -%>
68 <td class="<%= @permissions[status.id][field] %>">
68 <td class="<%= @permissions[status.id][field] %>">
69 <%= field_permission_tag(@permissions, status, field, @roles) %>
69 <%= field_permission_tag(@permissions, status, field, @roles) %>
70 <% unless status == @statuses.last %><a href="#" class="repeat-value">&#187;</a><% end %>
70 <% unless status == @statuses.last %><a href="#" class="repeat-value">&#187;</a><% end %>
71 </td>
71 </td>
72 <% end -%>
72 <% end -%>
73 </tr>
73 </tr>
74 <% end %>
74 <% end %>
75 <% if @custom_fields.any? %>
75 <% if @custom_fields.any? %>
76 <tr class="group open">
76 <tr class="group open">
77 <td colspan="<%= @statuses.size + 1 %>">
77 <td colspan="<%= @statuses.size + 1 %>">
78 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
78 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
79 <%= l(:label_custom_field_plural) %>
79 <%= l(:label_custom_field_plural) %>
80 </td>
80 </td>
81 </tr>
81 </tr>
82 <% @custom_fields.each do |field| %>
82 <% @custom_fields.each do |field| %>
83 <tr class="<%= cycle("odd", "even") %>">
83 <tr class="<%= cycle("odd", "even") %>">
84 <td class="name">
84 <td class="name">
85 <%=h field.name %> <%= content_tag('span', '*', :class => 'required') if field_required?(field) %>
85 <%=h field.name %> <%= content_tag('span', '*', :class => 'required') if field_required?(field) %>
86 </td>
86 </td>
87 <% for status in @statuses -%>
87 <% for status in @statuses -%>
88 <td class="<%= @permissions[status.id][field.id.to_s] %>">
88 <td class="<%= @permissions[status.id][field.id.to_s] %>">
89 <%= field_permission_tag(@permissions, status, field, @roles) %>
89 <%= field_permission_tag(@permissions, status, field, @roles) %>
90 <% unless status == @statuses.last %><a href="#" class="repeat-value">&#187;</a><% end %>
90 <% unless status == @statuses.last %><a href="#" class="repeat-value">&#187;</a><% end %>
91 </td>
91 </td>
92 <% end -%>
92 <% end -%>
93 </tr>
93 </tr>
94 <% end %>
94 <% end %>
95 <% end %>
95 <% end %>
96 </tbody>
96 </tbody>
97 </table>
97 </table>
98 </div>
98 </div>
99 <%= submit_tag l(:button_save) %>
99 <%= submit_tag l(:button_save) %>
100 <% end %>
100 <% end %>
101 <% end %>
101 <% end %>
102
102
103 <%= javascript_tag do %>
103 <%= javascript_tag do %>
104 $("a.repeat-value").click(function(e){
104 $("a.repeat-value").click(function(e){
105 e.preventDefault();
105 e.preventDefault();
106 var td = $(this).closest('td');
106 var td = $(this).closest('td');
107 var selected = td.find("select").find(":selected").val();
107 var selected = td.find("select").find(":selected").val();
108 td.nextAll('td').find("select").val(selected);
108 td.nextAll('td').find("select").val(selected);
109 });
109 });
110
110
111 $("a[data-expands]").click(function(e){
111 $("a[data-expands]").click(function(e){
112 e.preventDefault();
112 e.preventDefault();
113 var target = $($(this).attr("data-expands"));
113 var target = $($(this).attr("data-expands"));
114 if (target.attr("multiple")) {
114 if (target.attr("multiple")) {
115 target.attr("multiple", false);
115 target.attr("multiple", false);
116 target.find("option[value=all]").show();
116 target.find("option[value=all]").show();
117 } else {
117 } else {
118 target.attr("multiple", true);
118 target.attr("multiple", true);
119 target.find("option[value=all]").attr("selected", false).hide();
119 target.find("option[value=all]").attr("selected", false).hide();
120 }
120 }
121 });
121 });
122
122
123 <% end %>
123 <% end %>
General Comments 0
You need to be logged in to leave comments. Login now