##// END OF EJS Templates
Fixed: Manage pu(b)lic queries typo (Thomas Lecavelier)....
Jean-Philippe Lang -
r767:665497f5fbdf
parent child
Show More
@@ -1,81 +1,81
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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 QueriesController < ApplicationController
18 class QueriesController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def index
22 def index
23 @queries = @project.queries.find(:all,
23 @queries = @project.queries.find(:all,
24 :order => "name ASC",
24 :order => "name ASC",
25 :conditions => ["is_public = ? or user_id = ?", true, (logged_in_user ? logged_in_user.id : 0)])
25 :conditions => ["is_public = ? or user_id = ?", true, (logged_in_user ? logged_in_user.id : 0)])
26 end
26 end
27
27
28 def new
28 def new
29 @query = Query.new(params[:query])
29 @query = Query.new(params[:query])
30 @query.project = @project
30 @query.project = @project
31 @query.user = logged_in_user
31 @query.user = logged_in_user
32 @query.executed_by = logged_in_user
32 @query.executed_by = logged_in_user
33 @query.is_public = false unless current_role.allowed_to?(:manage_pulic_queries)
33 @query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
34
34
35 params[:fields].each do |field|
35 params[:fields].each do |field|
36 @query.add_filter(field, params[:operators][field], params[:values][field])
36 @query.add_filter(field, params[:operators][field], params[:values][field])
37 end if params[:fields]
37 end if params[:fields]
38
38
39 if request.post? and @query.save
39 if request.post? and @query.save
40 flash[:notice] = l(:notice_successful_create)
40 flash[:notice] = l(:notice_successful_create)
41 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
41 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
42 return
42 return
43 end
43 end
44 render :layout => false if request.xhr?
44 render :layout => false if request.xhr?
45 end
45 end
46
46
47 def edit
47 def edit
48 if request.post?
48 if request.post?
49 @query.filters = {}
49 @query.filters = {}
50 params[:fields].each do |field|
50 params[:fields].each do |field|
51 @query.add_filter(field, params[:operators][field], params[:values][field])
51 @query.add_filter(field, params[:operators][field], params[:values][field])
52 end if params[:fields]
52 end if params[:fields]
53 @query.attributes = params[:query]
53 @query.attributes = params[:query]
54 @query.is_public = false unless current_role.allowed_to?(:manage_pulic_queries)
54 @query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
55
55
56 if @query.save
56 if @query.save
57 flash[:notice] = l(:notice_successful_update)
57 flash[:notice] = l(:notice_successful_update)
58 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
58 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
59 end
59 end
60 end
60 end
61 end
61 end
62
62
63 def destroy
63 def destroy
64 @query.destroy if request.post?
64 @query.destroy if request.post?
65 redirect_to :controller => 'queries', :project_id => @project
65 redirect_to :controller => 'queries', :project_id => @project
66 end
66 end
67
67
68 private
68 private
69 def find_project
69 def find_project
70 if params[:id]
70 if params[:id]
71 @query = Query.find(params[:id])
71 @query = Query.find(params[:id])
72 @query.executed_by = logged_in_user
72 @query.executed_by = logged_in_user
73 @project = @query.project
73 @project = @query.project
74 render_403 unless @query.editable_by?(logged_in_user)
74 render_403 unless @query.editable_by?(logged_in_user)
75 else
75 else
76 @project = Project.find(params[:project_id])
76 @project = Project.find(params[:project_id])
77 end
77 end
78 rescue ActiveRecord::RecordNotFound
78 rescue ActiveRecord::RecordNotFound
79 render_404
79 render_404
80 end
80 end
81 end
81 end
@@ -1,265 +1,265
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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 Query < ActiveRecord::Base
18 class Query < ActiveRecord::Base
19 belongs_to :project
19 belongs_to :project
20 belongs_to :user
20 belongs_to :user
21 serialize :filters
21 serialize :filters
22
22
23 attr_protected :project, :user
23 attr_protected :project, :user
24 attr_accessor :executed_by
24 attr_accessor :executed_by
25
25
26 validates_presence_of :name, :on => :save
26 validates_presence_of :name, :on => :save
27 validates_length_of :name, :maximum => 255
27 validates_length_of :name, :maximum => 255
28
28
29 @@operators = { "=" => :label_equals,
29 @@operators = { "=" => :label_equals,
30 "!" => :label_not_equals,
30 "!" => :label_not_equals,
31 "o" => :label_open_issues,
31 "o" => :label_open_issues,
32 "c" => :label_closed_issues,
32 "c" => :label_closed_issues,
33 "!*" => :label_none,
33 "!*" => :label_none,
34 "*" => :label_all,
34 "*" => :label_all,
35 ">=" => '>=',
35 ">=" => '>=',
36 "<=" => '<=',
36 "<=" => '<=',
37 "<t+" => :label_in_less_than,
37 "<t+" => :label_in_less_than,
38 ">t+" => :label_in_more_than,
38 ">t+" => :label_in_more_than,
39 "t+" => :label_in,
39 "t+" => :label_in,
40 "t" => :label_today,
40 "t" => :label_today,
41 "w" => :label_this_week,
41 "w" => :label_this_week,
42 ">t-" => :label_less_than_ago,
42 ">t-" => :label_less_than_ago,
43 "<t-" => :label_more_than_ago,
43 "<t-" => :label_more_than_ago,
44 "t-" => :label_ago,
44 "t-" => :label_ago,
45 "~" => :label_contains,
45 "~" => :label_contains,
46 "!~" => :label_not_contains }
46 "!~" => :label_not_contains }
47
47
48 cattr_reader :operators
48 cattr_reader :operators
49
49
50 @@operators_by_filter_type = { :list => [ "=", "!" ],
50 @@operators_by_filter_type = { :list => [ "=", "!" ],
51 :list_status => [ "o", "=", "!", "c", "*" ],
51 :list_status => [ "o", "=", "!", "c", "*" ],
52 :list_optional => [ "=", "!", "!*", "*" ],
52 :list_optional => [ "=", "!", "!*", "*" ],
53 :list_one_or_more => [ "*", "=" ],
53 :list_one_or_more => [ "*", "=" ],
54 :date => [ "<t+", ">t+", "t+", "t", "w", ">t-", "<t-", "t-" ],
54 :date => [ "<t+", ">t+", "t+", "t", "w", ">t-", "<t-", "t-" ],
55 :date_past => [ ">t-", "<t-", "t-", "t", "w" ],
55 :date_past => [ ">t-", "<t-", "t-", "t", "w" ],
56 :string => [ "=", "~", "!", "!~" ],
56 :string => [ "=", "~", "!", "!~" ],
57 :text => [ "~", "!~" ],
57 :text => [ "~", "!~" ],
58 :integer => [ "=", ">=", "<=" ] }
58 :integer => [ "=", ">=", "<=" ] }
59
59
60 cattr_reader :operators_by_filter_type
60 cattr_reader :operators_by_filter_type
61
61
62 def initialize(attributes = nil)
62 def initialize(attributes = nil)
63 super attributes
63 super attributes
64 self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
64 self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
65 end
65 end
66
66
67 def executed_by=(user)
67 def executed_by=(user)
68 @executed_by = user
68 @executed_by = user
69 set_language_if_valid(user.language) if user
69 set_language_if_valid(user.language) if user
70 end
70 end
71
71
72 def validate
72 def validate
73 filters.each_key do |field|
73 filters.each_key do |field|
74 errors.add label_for(field), :activerecord_error_blank unless
74 errors.add label_for(field), :activerecord_error_blank unless
75 # filter requires one or more values
75 # filter requires one or more values
76 (values_for(field) and !values_for(field).first.empty?) or
76 (values_for(field) and !values_for(field).first.empty?) or
77 # filter doesn't require any value
77 # filter doesn't require any value
78 ["o", "c", "!*", "*", "t", "w"].include? operator_for(field)
78 ["o", "c", "!*", "*", "t", "w"].include? operator_for(field)
79 end if filters
79 end if filters
80 end
80 end
81
81
82 def editable_by?(user)
82 def editable_by?(user)
83 return false unless user
83 return false unless user
84 return true if !is_public && self.user_id == user.id
84 return true if !is_public && self.user_id == user.id
85 is_public && user.allowed_to?(:manage_pulic_queries, project)
85 is_public && user.allowed_to?(:manage_public_queries, project)
86 end
86 end
87
87
88 def available_filters
88 def available_filters
89 return @available_filters if @available_filters
89 return @available_filters if @available_filters
90 @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
90 @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
91 "tracker_id" => { :type => :list, :order => 2, :values => Tracker.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
91 "tracker_id" => { :type => :list, :order => 2, :values => Tracker.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
92 "priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
92 "priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
93 "subject" => { :type => :text, :order => 8 },
93 "subject" => { :type => :text, :order => 8 },
94 "created_on" => { :type => :date_past, :order => 9 },
94 "created_on" => { :type => :date_past, :order => 9 },
95 "updated_on" => { :type => :date_past, :order => 10 },
95 "updated_on" => { :type => :date_past, :order => 10 },
96 "start_date" => { :type => :date, :order => 11 },
96 "start_date" => { :type => :date, :order => 11 },
97 "due_date" => { :type => :date, :order => 12 },
97 "due_date" => { :type => :date, :order => 12 },
98 "done_ratio" => { :type => :integer, :order => 13 }}
98 "done_ratio" => { :type => :integer, :order => 13 }}
99
99
100 user_values = []
100 user_values = []
101 if project
101 if project
102 user_values += project.users.collect{|s| [s.name, s.id.to_s] }
102 user_values += project.users.collect{|s| [s.name, s.id.to_s] }
103 elsif executed_by
103 elsif executed_by
104 user_values << ["<< #{l(:label_me)} >>", "me"] if executed_by
104 user_values << ["<< #{l(:label_me)} >>", "me"] if executed_by
105 # members of the user's projects
105 # members of the user's projects
106 user_values += executed_by.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] }
106 user_values += executed_by.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] }
107 end
107 end
108 @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
108 @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
109 @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
109 @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
110
110
111 if project
111 if project
112 # project specific filters
112 # project specific filters
113 @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
113 @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
114 @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } }
114 @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } }
115 unless @project.active_children.empty?
115 unless @project.active_children.empty?
116 @available_filters["subproject_id"] = { :type => :list_one_or_more, :order => 13, :values => @project.active_children.collect{|s| [s.name, s.id.to_s] } }
116 @available_filters["subproject_id"] = { :type => :list_one_or_more, :order => 13, :values => @project.active_children.collect{|s| [s.name, s.id.to_s] } }
117 end
117 end
118 @project.all_custom_fields.select(&:is_filter?).each do |field|
118 @project.all_custom_fields.select(&:is_filter?).each do |field|
119 case field.field_format
119 case field.field_format
120 when "string", "int"
120 when "string", "int"
121 options = { :type => :string, :order => 20 }
121 options = { :type => :string, :order => 20 }
122 when "text"
122 when "text"
123 options = { :type => :text, :order => 20 }
123 options = { :type => :text, :order => 20 }
124 when "list"
124 when "list"
125 options = { :type => :list_optional, :values => field.possible_values, :order => 20}
125 options = { :type => :list_optional, :values => field.possible_values, :order => 20}
126 when "date"
126 when "date"
127 options = { :type => :date, :order => 20 }
127 options = { :type => :date, :order => 20 }
128 when "bool"
128 when "bool"
129 options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 }
129 options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 }
130 end
130 end
131 @available_filters["cf_#{field.id}"] = options.merge({ :name => field.name })
131 @available_filters["cf_#{field.id}"] = options.merge({ :name => field.name })
132 end
132 end
133 # remove category filter if no category defined
133 # remove category filter if no category defined
134 @available_filters.delete "category_id" if @available_filters["category_id"][:values].empty?
134 @available_filters.delete "category_id" if @available_filters["category_id"][:values].empty?
135 end
135 end
136 @available_filters
136 @available_filters
137 end
137 end
138
138
139 def add_filter(field, operator, values)
139 def add_filter(field, operator, values)
140 # values must be an array
140 # values must be an array
141 return unless values and values.is_a? Array # and !values.first.empty?
141 return unless values and values.is_a? Array # and !values.first.empty?
142 # check if field is defined as an available filter
142 # check if field is defined as an available filter
143 if available_filters.has_key? field
143 if available_filters.has_key? field
144 filter_options = available_filters[field]
144 filter_options = available_filters[field]
145 # check if operator is allowed for that filter
145 # check if operator is allowed for that filter
146 #if @@operators_by_filter_type[filter_options[:type]].include? operator
146 #if @@operators_by_filter_type[filter_options[:type]].include? operator
147 # allowed_values = values & ([""] + (filter_options[:values] || []).collect {|val| val[1]})
147 # allowed_values = values & ([""] + (filter_options[:values] || []).collect {|val| val[1]})
148 # filters[field] = {:operator => operator, :values => allowed_values } if (allowed_values.first and !allowed_values.first.empty?) or ["o", "c", "!*", "*", "t"].include? operator
148 # filters[field] = {:operator => operator, :values => allowed_values } if (allowed_values.first and !allowed_values.first.empty?) or ["o", "c", "!*", "*", "t"].include? operator
149 #end
149 #end
150 filters[field] = {:operator => operator, :values => values }
150 filters[field] = {:operator => operator, :values => values }
151 end
151 end
152 end
152 end
153
153
154 def add_short_filter(field, expression)
154 def add_short_filter(field, expression)
155 return unless expression
155 return unless expression
156 parms = expression.scan(/^(o|c|\!|\*)?(.*)$/).first
156 parms = expression.scan(/^(o|c|\!|\*)?(.*)$/).first
157 add_filter field, (parms[0] || "="), [parms[1] || ""]
157 add_filter field, (parms[0] || "="), [parms[1] || ""]
158 end
158 end
159
159
160 def has_filter?(field)
160 def has_filter?(field)
161 filters and filters[field]
161 filters and filters[field]
162 end
162 end
163
163
164 def operator_for(field)
164 def operator_for(field)
165 has_filter?(field) ? filters[field][:operator] : nil
165 has_filter?(field) ? filters[field][:operator] : nil
166 end
166 end
167
167
168 def values_for(field)
168 def values_for(field)
169 has_filter?(field) ? filters[field][:values] : nil
169 has_filter?(field) ? filters[field][:values] : nil
170 end
170 end
171
171
172 def label_for(field)
172 def label_for(field)
173 label = @available_filters[field][:name] if @available_filters.has_key?(field)
173 label = @available_filters[field][:name] if @available_filters.has_key?(field)
174 label ||= field.gsub(/\_id$/, "")
174 label ||= field.gsub(/\_id$/, "")
175 end
175 end
176
176
177 def statement
177 def statement
178 # project/subprojects clause
178 # project/subprojects clause
179 clause = ''
179 clause = ''
180 if project && has_filter?("subproject_id")
180 if project && has_filter?("subproject_id")
181 subproject_ids = []
181 subproject_ids = []
182 if operator_for("subproject_id") == "="
182 if operator_for("subproject_id") == "="
183 subproject_ids = values_for("subproject_id").each(&:to_i)
183 subproject_ids = values_for("subproject_id").each(&:to_i)
184 else
184 else
185 subproject_ids = project.active_children.collect{|p| p.id}
185 subproject_ids = project.active_children.collect{|p| p.id}
186 end
186 end
187 clause << "#{Issue.table_name}.project_id IN (%d,%s)" % [project.id, subproject_ids.join(",")] if project
187 clause << "#{Issue.table_name}.project_id IN (%d,%s)" % [project.id, subproject_ids.join(",")] if project
188 elsif project
188 elsif project
189 clause << "#{Issue.table_name}.project_id=%d" % project.id
189 clause << "#{Issue.table_name}.project_id=%d" % project.id
190 else
190 else
191 clause << Project.visible_by(executed_by)
191 clause << Project.visible_by(executed_by)
192 end
192 end
193
193
194 # filters clauses
194 # filters clauses
195 filters_clauses = []
195 filters_clauses = []
196 filters.each_key do |field|
196 filters.each_key do |field|
197 next if field == "subproject_id"
197 next if field == "subproject_id"
198 v = values_for(field).clone
198 v = values_for(field).clone
199 next unless v and !v.empty?
199 next unless v and !v.empty?
200
200
201 sql = ''
201 sql = ''
202 if field =~ /^cf_(\d+)$/
202 if field =~ /^cf_(\d+)$/
203 # custom field
203 # custom field
204 db_table = CustomValue.table_name
204 db_table = CustomValue.table_name
205 db_field = 'value'
205 db_field = 'value'
206 sql << "#{Issue.table_name}.id IN (SELECT #{db_table}.customized_id FROM #{db_table} where #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{$1} AND "
206 sql << "#{Issue.table_name}.id IN (SELECT #{db_table}.customized_id FROM #{db_table} where #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{$1} AND "
207 else
207 else
208 # regular field
208 # regular field
209 db_table = Issue.table_name
209 db_table = Issue.table_name
210 db_field = field
210 db_field = field
211 sql << '('
211 sql << '('
212 end
212 end
213
213
214 # "me" value subsitution
214 # "me" value subsitution
215 if %w(assigned_to_id author_id).include?(field)
215 if %w(assigned_to_id author_id).include?(field)
216 v.push(executed_by ? executed_by.id.to_s : "0") if v.delete("me")
216 v.push(executed_by ? executed_by.id.to_s : "0") if v.delete("me")
217 end
217 end
218
218
219 case operator_for field
219 case operator_for field
220 when "="
220 when "="
221 sql = sql + "#{db_table}.#{db_field} IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
221 sql = sql + "#{db_table}.#{db_field} IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
222 when "!"
222 when "!"
223 sql = sql + "#{db_table}.#{db_field} NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
223 sql = sql + "#{db_table}.#{db_field} NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
224 when "!*"
224 when "!*"
225 sql = sql + "#{db_table}.#{db_field} IS NULL"
225 sql = sql + "#{db_table}.#{db_field} IS NULL"
226 when "*"
226 when "*"
227 sql = sql + "#{db_table}.#{db_field} IS NOT NULL"
227 sql = sql + "#{db_table}.#{db_field} IS NOT NULL"
228 when ">="
228 when ">="
229 sql = sql + "#{db_table}.#{db_field} >= #{v.first.to_i}"
229 sql = sql + "#{db_table}.#{db_field} >= #{v.first.to_i}"
230 when "<="
230 when "<="
231 sql = sql + "#{db_table}.#{db_field} <= #{v.first.to_i}"
231 sql = sql + "#{db_table}.#{db_field} <= #{v.first.to_i}"
232 when "o"
232 when "o"
233 sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_false}" if field == "status_id"
233 sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_false}" if field == "status_id"
234 when "c"
234 when "c"
235 sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_true}" if field == "status_id"
235 sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_true}" if field == "status_id"
236 when ">t-"
236 when ">t-"
237 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today - v.first.to_i).to_time), connection.quoted_date((Date.today + 1).to_time)]
237 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today - v.first.to_i).to_time), connection.quoted_date((Date.today + 1).to_time)]
238 when "<t-"
238 when "<t-"
239 sql = sql + "#{db_table}.#{db_field} <= '%s'" % connection.quoted_date((Date.today - v.first.to_i).to_time)
239 sql = sql + "#{db_table}.#{db_field} <= '%s'" % connection.quoted_date((Date.today - v.first.to_i).to_time)
240 when "t-"
240 when "t-"
241 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today - v.first.to_i).to_time), connection.quoted_date((Date.today - v.first.to_i + 1).to_time)]
241 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today - v.first.to_i).to_time), connection.quoted_date((Date.today - v.first.to_i + 1).to_time)]
242 when ">t+"
242 when ">t+"
243 sql = sql + "#{db_table}.#{db_field} >= '%s'" % connection.quoted_date((Date.today + v.first.to_i).to_time)
243 sql = sql + "#{db_table}.#{db_field} >= '%s'" % connection.quoted_date((Date.today + v.first.to_i).to_time)
244 when "<t+"
244 when "<t+"
245 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Date.today.to_time), connection.quoted_date((Date.today + v.first.to_i + 1).to_time)]
245 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Date.today.to_time), connection.quoted_date((Date.today + v.first.to_i + 1).to_time)]
246 when "t+"
246 when "t+"
247 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today + v.first.to_i).to_time), connection.quoted_date((Date.today + v.first.to_i + 1).to_time)]
247 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today + v.first.to_i).to_time), connection.quoted_date((Date.today + v.first.to_i + 1).to_time)]
248 when "t"
248 when "t"
249 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Date.today.to_time), connection.quoted_date((Date.today+1).to_time)]
249 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Date.today.to_time), connection.quoted_date((Date.today+1).to_time)]
250 when "w"
250 when "w"
251 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Time.now.at_beginning_of_week), connection.quoted_date(Time.now.next_week.yesterday)]
251 sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Time.now.at_beginning_of_week), connection.quoted_date(Time.now.next_week.yesterday)]
252 when "~"
252 when "~"
253 sql = sql + "#{db_table}.#{db_field} LIKE '%#{connection.quote_string(v.first)}%'"
253 sql = sql + "#{db_table}.#{db_field} LIKE '%#{connection.quote_string(v.first)}%'"
254 when "!~"
254 when "!~"
255 sql = sql + "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(v.first)}%'"
255 sql = sql + "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(v.first)}%'"
256 end
256 end
257 sql << ')'
257 sql << ')'
258 filters_clauses << sql
258 filters_clauses << sql
259 end if filters and valid?
259 end if filters and valid?
260
260
261 clause << ' AND ' unless clause.empty?
261 clause << ' AND ' unless clause.empty?
262 clause << filters_clauses.join(' AND ') unless filters_clauses.empty?
262 clause << filters_clauses.join(' AND ') unless filters_clauses.empty?
263 clause
263 clause
264 end
264 end
265 end
265 end
@@ -1,15 +1,15
1 <%= error_messages_for 'query' %>
1 <%= error_messages_for 'query' %>
2
2
3 <div class="box">
3 <div class="box">
4 <div class="tabular">
4 <div class="tabular">
5 <p><label for="query_name"><%=l(:field_name)%></label>
5 <p><label for="query_name"><%=l(:field_name)%></label>
6 <%= text_field 'query', 'name', :size => 80 %></p>
6 <%= text_field 'query', 'name', :size => 80 %></p>
7
7
8 <% if current_role.allowed_to?(:manage_pulic_queries) %>
8 <% if current_role.allowed_to?(:manage_public_queries) %>
9 <p><label for="query_is_public"><%=l(:field_is_public)%></label>
9 <p><label for="query_is_public"><%=l(:field_is_public)%></label>
10 <%= check_box 'query', 'is_public' %></p>
10 <%= check_box 'query', 'is_public' %></p>
11 <% end %>
11 <% end %>
12 </div>
12 </div>
13
13
14 <%= render :partial => 'queries/filters', :locals => {:query => query}%>
14 <%= render :partial => 'queries/filters', :locals => {:query => query}%>
15 </div>
15 </div>
@@ -1,101 +1,101
1 require 'redmine/access_control'
1 require 'redmine/access_control'
2 require 'redmine/menu_manager'
2 require 'redmine/menu_manager'
3 require 'redmine/mime_type'
3 require 'redmine/mime_type'
4 require 'redmine/plugin'
4 require 'redmine/plugin'
5
5
6 begin
6 begin
7 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
7 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
8 rescue LoadError
8 rescue LoadError
9 # RMagick is not available
9 # RMagick is not available
10 end
10 end
11
11
12 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs )
12 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs )
13
13
14 # Permissions
14 # Permissions
15 Redmine::AccessControl.map do |map|
15 Redmine::AccessControl.map do |map|
16 map.permission :view_project, {:projects => [:show, :activity, :feeds]}, :public => true
16 map.permission :view_project, {:projects => [:show, :activity, :feeds]}, :public => true
17 map.permission :search_project, {:search => :index}, :public => true
17 map.permission :search_project, {:search => :index}, :public => true
18 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
18 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
19 map.permission :select_project_modules, {:projects => :modules}, :require => :member
19 map.permission :select_project_modules, {:projects => :modules}, :require => :member
20 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
20 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
21 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
21 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
22
22
23 map.project_module :issue_tracking do |map|
23 map.project_module :issue_tracking do |map|
24 # Issue categories
24 # Issue categories
25 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
25 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
26 # Issues
26 # Issues
27 map.permission :view_issues, {:projects => [:list_issues, :export_issues_csv, :export_issues_pdf, :changelog, :roadmap],
27 map.permission :view_issues, {:projects => [:list_issues, :export_issues_csv, :export_issues_pdf, :changelog, :roadmap],
28 :issues => [:show, :export_pdf],
28 :issues => [:show, :export_pdf],
29 :queries => :index,
29 :queries => :index,
30 :reports => :issue_report}, :public => true
30 :reports => :issue_report}, :public => true
31 map.permission :add_issues, {:projects => :add_issue}, :require => :loggedin
31 map.permission :add_issues, {:projects => :add_issue}, :require => :loggedin
32 map.permission :edit_issues, {:issues => [:edit, :destroy_attachment]}, :require => :loggedin
32 map.permission :edit_issues, {:issues => [:edit, :destroy_attachment]}, :require => :loggedin
33 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}, :require => :loggedin
33 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}, :require => :loggedin
34 map.permission :add_issue_notes, {:issues => :add_note}, :require => :loggedin
34 map.permission :add_issue_notes, {:issues => :add_note}, :require => :loggedin
35 map.permission :change_issue_status, {:issues => :change_status}, :require => :loggedin
35 map.permission :change_issue_status, {:issues => :change_status}, :require => :loggedin
36 map.permission :move_issues, {:projects => :move_issues}, :require => :loggedin
36 map.permission :move_issues, {:projects => :move_issues}, :require => :loggedin
37 map.permission :delete_issues, {:issues => :destroy}, :require => :member
37 map.permission :delete_issues, {:issues => :destroy}, :require => :member
38 # Queries
38 # Queries
39 map.permission :manage_pulic_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
39 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
40 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
40 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
41 # Gantt & calendar
41 # Gantt & calendar
42 map.permission :view_gantt, :projects => :gantt
42 map.permission :view_gantt, :projects => :gantt
43 map.permission :view_calendar, :projects => :calendar
43 map.permission :view_calendar, :projects => :calendar
44 end
44 end
45
45
46 map.project_module :time_tracking do |map|
46 map.project_module :time_tracking do |map|
47 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
47 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
48 map.permission :view_time_entries, :timelog => [:details, :report]
48 map.permission :view_time_entries, :timelog => [:details, :report]
49 end
49 end
50
50
51 map.project_module :news do |map|
51 map.project_module :news do |map|
52 map.permission :manage_news, {:projects => :add_news, :news => [:edit, :destroy, :destroy_comment]}, :require => :member
52 map.permission :manage_news, {:projects => :add_news, :news => [:edit, :destroy, :destroy_comment]}, :require => :member
53 map.permission :view_news, {:projects => :list_news, :news => :show}, :public => true
53 map.permission :view_news, {:projects => :list_news, :news => :show}, :public => true
54 map.permission :comment_news, {:news => :add_comment}, :require => :loggedin
54 map.permission :comment_news, {:news => :add_comment}, :require => :loggedin
55 end
55 end
56
56
57 map.project_module :documents do |map|
57 map.project_module :documents do |map|
58 map.permission :manage_documents, {:projects => :add_document, :documents => [:edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
58 map.permission :manage_documents, {:projects => :add_document, :documents => [:edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
59 map.permission :view_documents, :projects => :list_documents, :documents => [:show, :download]
59 map.permission :view_documents, :projects => :list_documents, :documents => [:show, :download]
60 end
60 end
61
61
62 map.project_module :files do |map|
62 map.project_module :files do |map|
63 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
63 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
64 map.permission :view_files, :projects => :list_files, :versions => :download
64 map.permission :view_files, :projects => :list_files, :versions => :download
65 end
65 end
66
66
67 map.project_module :wiki do |map|
67 map.project_module :wiki do |map|
68 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
68 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
69 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
69 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
70 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
70 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
71 map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :special]
71 map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :special]
72 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
72 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
73 end
73 end
74
74
75 map.project_module :repository do |map|
75 map.project_module :repository do |map|
76 map.permission :manage_repository, :repositories => [:edit, :destroy]
76 map.permission :manage_repository, :repositories => [:edit, :destroy]
77 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :changes, :diff, :stats, :graph]
77 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :changes, :diff, :stats, :graph]
78 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
78 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
79 end
79 end
80
80
81 map.project_module :boards do |map|
81 map.project_module :boards do |map|
82 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
82 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
83 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
83 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
84 map.permission :add_messages, {:messages => [:new, :reply]}, :require => :loggedin
84 map.permission :add_messages, {:messages => [:new, :reply]}, :require => :loggedin
85 end
85 end
86 end
86 end
87
87
88 # Project menu configuration
88 # Project menu configuration
89 Redmine::MenuManager.map :project_menu do |menu|
89 Redmine::MenuManager.map :project_menu do |menu|
90 menu.push :label_overview, :controller => 'projects', :action => 'show'
90 menu.push :label_overview, :controller => 'projects', :action => 'show'
91 menu.push :label_activity, :controller => 'projects', :action => 'activity'
91 menu.push :label_activity, :controller => 'projects', :action => 'activity'
92 menu.push :label_roadmap, :controller => 'projects', :action => 'roadmap'
92 menu.push :label_roadmap, :controller => 'projects', :action => 'roadmap'
93 menu.push :label_issue_plural, :controller => 'projects', :action => 'list_issues'
93 menu.push :label_issue_plural, :controller => 'projects', :action => 'list_issues'
94 menu.push :label_news_plural, :controller => 'projects', :action => 'list_news'
94 menu.push :label_news_plural, :controller => 'projects', :action => 'list_news'
95 menu.push :label_document_plural, :controller => 'projects', :action => 'list_documents'
95 menu.push :label_document_plural, :controller => 'projects', :action => 'list_documents'
96 menu.push :label_wiki, { :controller => 'wiki', :action => 'index', :page => nil }, :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
96 menu.push :label_wiki, { :controller => 'wiki', :action => 'index', :page => nil }, :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
97 menu.push :label_board_plural, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id, :if => Proc.new { |p| p.boards.any? }
97 menu.push :label_board_plural, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id, :if => Proc.new { |p| p.boards.any? }
98 menu.push :label_attachment_plural, :controller => 'projects', :action => 'list_files'
98 menu.push :label_attachment_plural, :controller => 'projects', :action => 'list_files'
99 menu.push :label_repository, { :controller => 'repositories', :action => 'show' }, :if => Proc.new { |p| p.repository && !p.repository.new_record? }
99 menu.push :label_repository, { :controller => 'repositories', :action => 'show' }, :if => Proc.new { |p| p.repository && !p.repository.new_record? }
100 menu.push :label_settings, :controller => 'projects', :action => 'settings'
100 menu.push :label_settings, :controller => 'projects', :action => 'settings'
101 end
101 end
@@ -1,161 +1,161
1 ---
1 ---
2 roles_004:
2 roles_004:
3 name: Non member
3 name: Non member
4 id: 4
4 id: 4
5 builtin: 1
5 builtin: 1
6 permissions: |
6 permissions: |
7 ---
7 ---
8 - :add_issues
8 - :add_issues
9 - :edit_issues
9 - :edit_issues
10 - :manage_issue_relations
10 - :manage_issue_relations
11 - :add_issue_notes
11 - :add_issue_notes
12 - :change_issue_status
12 - :change_issue_status
13 - :move_issues
13 - :move_issues
14 - :save_queries
14 - :save_queries
15 - :view_gantt
15 - :view_gantt
16 - :view_calendar
16 - :view_calendar
17 - :log_time
17 - :log_time
18 - :view_time_entries
18 - :view_time_entries
19 - :comment_news
19 - :comment_news
20 - :view_documents
20 - :view_documents
21 - :manage_documents
21 - :manage_documents
22 - :view_wiki_pages
22 - :view_wiki_pages
23 - :edit_wiki_pages
23 - :edit_wiki_pages
24 - :add_messages
24 - :add_messages
25 - :view_files
25 - :view_files
26 - :manage_files
26 - :manage_files
27 - :browse_repository
27 - :browse_repository
28 - :view_changesets
28 - :view_changesets
29
29
30 position: 5
30 position: 5
31 roles_005:
31 roles_005:
32 name: Anonymous
32 name: Anonymous
33 id: 5
33 id: 5
34 builtin: 2
34 builtin: 2
35 permissions: |
35 permissions: |
36 ---
36 ---
37 - :view_gantt
37 - :view_gantt
38 - :view_calendar
38 - :view_calendar
39 - :view_time_entries
39 - :view_time_entries
40 - :view_documents
40 - :view_documents
41 - :view_wiki_pages
41 - :view_wiki_pages
42 - :edit_wiki_pages
42 - :edit_wiki_pages
43 - :view_files
43 - :view_files
44 - :browse_repository
44 - :browse_repository
45 - :view_changesets
45 - :view_changesets
46
46
47 position: 6
47 position: 6
48 roles_001:
48 roles_001:
49 name: Manager
49 name: Manager
50 id: 1
50 id: 1
51 builtin: 0
51 builtin: 0
52 permissions: |
52 permissions: |
53 ---
53 ---
54 - :edit_project
54 - :edit_project
55 - :manage_members
55 - :manage_members
56 - :manage_versions
56 - :manage_versions
57 - :manage_categories
57 - :manage_categories
58 - :add_issues
58 - :add_issues
59 - :edit_issues
59 - :edit_issues
60 - :manage_issue_relations
60 - :manage_issue_relations
61 - :add_issue_notes
61 - :add_issue_notes
62 - :change_issue_status
62 - :change_issue_status
63 - :move_issues
63 - :move_issues
64 - :delete_issues
64 - :delete_issues
65 - :manage_pulic_queries
65 - :manage_public_queries
66 - :save_queries
66 - :save_queries
67 - :view_gantt
67 - :view_gantt
68 - :view_calendar
68 - :view_calendar
69 - :log_time
69 - :log_time
70 - :view_time_entries
70 - :view_time_entries
71 - :manage_news
71 - :manage_news
72 - :comment_news
72 - :comment_news
73 - :view_documents
73 - :view_documents
74 - :manage_documents
74 - :manage_documents
75 - :view_wiki_pages
75 - :view_wiki_pages
76 - :edit_wiki_pages
76 - :edit_wiki_pages
77 - :delete_wiki_pages
77 - :delete_wiki_pages
78 - :add_messages
78 - :add_messages
79 - :manage_boards
79 - :manage_boards
80 - :view_files
80 - :view_files
81 - :manage_files
81 - :manage_files
82 - :browse_repository
82 - :browse_repository
83 - :view_changesets
83 - :view_changesets
84
84
85 position: 2
85 position: 2
86 roles_002:
86 roles_002:
87 name: Developer
87 name: Developer
88 id: 2
88 id: 2
89 builtin: 0
89 builtin: 0
90 permissions: |
90 permissions: |
91 ---
91 ---
92 - :edit_project
92 - :edit_project
93 - :manage_members
93 - :manage_members
94 - :manage_versions
94 - :manage_versions
95 - :manage_categories
95 - :manage_categories
96 - :add_issues
96 - :add_issues
97 - :edit_issues
97 - :edit_issues
98 - :manage_issue_relations
98 - :manage_issue_relations
99 - :add_issue_notes
99 - :add_issue_notes
100 - :change_issue_status
100 - :change_issue_status
101 - :move_issues
101 - :move_issues
102 - :delete_issues
102 - :delete_issues
103 - :manage_pulic_queries
103 - :manage_public_queries
104 - :save_queries
104 - :save_queries
105 - :view_gantt
105 - :view_gantt
106 - :view_calendar
106 - :view_calendar
107 - :log_time
107 - :log_time
108 - :view_time_entries
108 - :view_time_entries
109 - :manage_news
109 - :manage_news
110 - :comment_news
110 - :comment_news
111 - :view_documents
111 - :view_documents
112 - :manage_documents
112 - :manage_documents
113 - :view_wiki_pages
113 - :view_wiki_pages
114 - :edit_wiki_pages
114 - :edit_wiki_pages
115 - :delete_wiki_pages
115 - :delete_wiki_pages
116 - :add_messages
116 - :add_messages
117 - :manage_boards
117 - :manage_boards
118 - :view_files
118 - :view_files
119 - :manage_files
119 - :manage_files
120 - :browse_repository
120 - :browse_repository
121 - :view_changesets
121 - :view_changesets
122
122
123 position: 3
123 position: 3
124 roles_003:
124 roles_003:
125 name: Reporter
125 name: Reporter
126 id: 3
126 id: 3
127 builtin: 0
127 builtin: 0
128 permissions: |
128 permissions: |
129 ---
129 ---
130 - :edit_project
130 - :edit_project
131 - :manage_members
131 - :manage_members
132 - :manage_versions
132 - :manage_versions
133 - :manage_categories
133 - :manage_categories
134 - :add_issues
134 - :add_issues
135 - :edit_issues
135 - :edit_issues
136 - :manage_issue_relations
136 - :manage_issue_relations
137 - :add_issue_notes
137 - :add_issue_notes
138 - :change_issue_status
138 - :change_issue_status
139 - :move_issues
139 - :move_issues
140 - :delete_issues
140 - :delete_issues
141 - :manage_pulic_queries
141 - :manage_public_queries
142 - :save_queries
142 - :save_queries
143 - :view_gantt
143 - :view_gantt
144 - :view_calendar
144 - :view_calendar
145 - :log_time
145 - :log_time
146 - :view_time_entries
146 - :view_time_entries
147 - :manage_news
147 - :manage_news
148 - :comment_news
148 - :comment_news
149 - :view_documents
149 - :view_documents
150 - :manage_documents
150 - :manage_documents
151 - :view_wiki_pages
151 - :view_wiki_pages
152 - :edit_wiki_pages
152 - :edit_wiki_pages
153 - :delete_wiki_pages
153 - :delete_wiki_pages
154 - :add_messages
154 - :add_messages
155 - :manage_boards
155 - :manage_boards
156 - :view_files
156 - :view_files
157 - :manage_files
157 - :manage_files
158 - :browse_repository
158 - :browse_repository
159 - :view_changesets
159 - :view_changesets
160
160
161 position: 4
161 position: 4
General Comments 0
You need to be logged in to leave comments. Login now