##// END OF EJS Templates
various eager loadings added...
Jean-Philippe Lang -
r95:3e28dc669b01
parent child
Show More
@@ -1,126 +1,126
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 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 ApplicationController < ActionController::Base
18 class ApplicationController < ActionController::Base
19 before_filter :check_if_login_required, :set_localization
19 before_filter :check_if_login_required, :set_localization
20
20
21 def logged_in_user=(user)
21 def logged_in_user=(user)
22 @logged_in_user = user
22 @logged_in_user = user
23 session[:user_id] = (user ? user.id : nil)
23 session[:user_id] = (user ? user.id : nil)
24 end
24 end
25
25
26 def logged_in_user
26 def logged_in_user
27 if session[:user_id]
27 if session[:user_id]
28 @logged_in_user ||= User.find(session[:user_id], :include => :memberships)
28 @logged_in_user ||= User.find(session[:user_id])
29 else
29 else
30 nil
30 nil
31 end
31 end
32 end
32 end
33
33
34 # check if login is globally required to access the application
34 # check if login is globally required to access the application
35 def check_if_login_required
35 def check_if_login_required
36 require_login if $RDM_LOGIN_REQUIRED
36 require_login if $RDM_LOGIN_REQUIRED
37 end
37 end
38
38
39 def set_localization
39 def set_localization
40 lang = begin
40 lang = begin
41 if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym
41 if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym
42 self.logged_in_user.language
42 self.logged_in_user.language
43 elsif request.env['HTTP_ACCEPT_LANGUAGE']
43 elsif request.env['HTTP_ACCEPT_LANGUAGE']
44 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
44 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
45 if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
45 if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
46 accept_lang
46 accept_lang
47 end
47 end
48 end
48 end
49 rescue
49 rescue
50 nil
50 nil
51 end || $RDM_DEFAULT_LANG
51 end || $RDM_DEFAULT_LANG
52 set_language_if_valid(lang)
52 set_language_if_valid(lang)
53 end
53 end
54
54
55 def require_login
55 def require_login
56 unless self.logged_in_user
56 unless self.logged_in_user
57 store_location
57 store_location
58 redirect_to :controller => "account", :action => "login"
58 redirect_to :controller => "account", :action => "login"
59 return false
59 return false
60 end
60 end
61 true
61 true
62 end
62 end
63
63
64 def require_admin
64 def require_admin
65 return unless require_login
65 return unless require_login
66 unless self.logged_in_user.admin?
66 unless self.logged_in_user.admin?
67 render :nothing => true, :status => 403
67 render :nothing => true, :status => 403
68 return false
68 return false
69 end
69 end
70 true
70 true
71 end
71 end
72
72
73 # authorizes the user for the requested action.
73 # authorizes the user for the requested action.
74 def authorize(ctrl = @params[:controller], action = @params[:action])
74 def authorize(ctrl = @params[:controller], action = @params[:action])
75 # check if action is allowed on public projects
75 # check if action is allowed on public projects
76 if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ]
76 if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ]
77 return true
77 return true
78 end
78 end
79 # if action is not public, force login
79 # if action is not public, force login
80 return unless require_login
80 return unless require_login
81 # admin is always authorized
81 # admin is always authorized
82 return true if self.logged_in_user.admin?
82 return true if self.logged_in_user.admin?
83 # if not admin, check membership permission
83 # if not admin, check membership permission
84 @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id])
84 @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id])
85 if @user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], @user_membership.role_id )
85 if @user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], @user_membership.role_id )
86 return true
86 return true
87 end
87 end
88 render :nothing => true, :status => 403
88 render :nothing => true, :status => 403
89 false
89 false
90 end
90 end
91
91
92 # store current uri in session.
92 # store current uri in session.
93 # return to this location by calling redirect_back_or_default
93 # return to this location by calling redirect_back_or_default
94 def store_location
94 def store_location
95 session[:return_to] = @request.request_uri
95 session[:return_to] = @request.request_uri
96 end
96 end
97
97
98 # move to the last store_location call or to the passed default one
98 # move to the last store_location call or to the passed default one
99 def redirect_back_or_default(default)
99 def redirect_back_or_default(default)
100 if session[:return_to].nil?
100 if session[:return_to].nil?
101 redirect_to default
101 redirect_to default
102 else
102 else
103 redirect_to_url session[:return_to]
103 redirect_to_url session[:return_to]
104 session[:return_to] = nil
104 session[:return_to] = nil
105 end
105 end
106 end
106 end
107
107
108 # qvalues http header parser
108 # qvalues http header parser
109 # code taken from webrick
109 # code taken from webrick
110 def parse_qvalues(value)
110 def parse_qvalues(value)
111 tmp = []
111 tmp = []
112 if value
112 if value
113 parts = value.split(/,\s*/)
113 parts = value.split(/,\s*/)
114 parts.each {|part|
114 parts.each {|part|
115 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
115 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
116 val = m[1]
116 val = m[1]
117 q = (m[2] or 1).to_f
117 q = (m[2] or 1).to_f
118 tmp.push([val, q])
118 tmp.push([val, q])
119 end
119 end
120 }
120 }
121 tmp = tmp.sort_by{|val, q| -q}
121 tmp = tmp.sort_by{|val, q| -q}
122 tmp.collect!{|val, q| val}
122 tmp.collect!{|val, q| val}
123 end
123 end
124 return tmp
124 return tmp
125 end
125 end
126 end No newline at end of file
126 end
@@ -1,516 +1,516
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 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 ProjectsController < ApplicationController
18 class ProjectsController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
20 before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
21 before_filter :require_admin, :only => [ :add, :destroy ]
21 before_filter :require_admin, :only => [ :add, :destroy ]
22
22
23 helper :sort
23 helper :sort
24 include SortHelper
24 include SortHelper
25 helper :custom_fields
25 helper :custom_fields
26 include CustomFieldsHelper
26 include CustomFieldsHelper
27 helper :ifpdf
27 helper :ifpdf
28 include IfpdfHelper
28 include IfpdfHelper
29 helper IssuesHelper
29 helper IssuesHelper
30 helper :queries
30 helper :queries
31 include QueriesHelper
31 include QueriesHelper
32
32
33 def index
33 def index
34 list
34 list
35 render :action => 'list' unless request.xhr?
35 render :action => 'list' unless request.xhr?
36 end
36 end
37
37
38 # Lists public projects
38 # Lists public projects
39 def list
39 def list
40 sort_init 'name', 'asc'
40 sort_init 'name', 'asc'
41 sort_update
41 sort_update
42 @project_count = Project.count(["is_public=?", true])
42 @project_count = Project.count(["is_public=?", true])
43 @project_pages = Paginator.new self, @project_count,
43 @project_pages = Paginator.new self, @project_count,
44 15,
44 15,
45 @params['page']
45 @params['page']
46 @projects = Project.find :all, :order => sort_clause,
46 @projects = Project.find :all, :order => sort_clause,
47 :conditions => ["is_public=?", true],
47 :conditions => ["is_public=?", true],
48 :limit => @project_pages.items_per_page,
48 :limit => @project_pages.items_per_page,
49 :offset => @project_pages.current.offset
49 :offset => @project_pages.current.offset
50
50
51 render :action => "list", :layout => false if request.xhr?
51 render :action => "list", :layout => false if request.xhr?
52 end
52 end
53
53
54 # Add a new project
54 # Add a new project
55 def add
55 def add
56 @custom_fields = IssueCustomField.find(:all)
56 @custom_fields = IssueCustomField.find(:all)
57 @root_projects = Project.find(:all, :conditions => "parent_id is null")
57 @root_projects = Project.find(:all, :conditions => "parent_id is null")
58 @project = Project.new(params[:project])
58 @project = Project.new(params[:project])
59 if request.get?
59 if request.get?
60 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
60 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
61 else
61 else
62 @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
62 @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
63 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
63 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
64 @project.custom_values = @custom_values
64 @project.custom_values = @custom_values
65 if @project.save
65 if @project.save
66 flash[:notice] = l(:notice_successful_create)
66 flash[:notice] = l(:notice_successful_create)
67 redirect_to :controller => 'admin', :action => 'projects'
67 redirect_to :controller => 'admin', :action => 'projects'
68 end
68 end
69 end
69 end
70 end
70 end
71
71
72 # Show @project
72 # Show @project
73 def show
73 def show
74 @custom_values = @project.custom_values.find(:all, :include => :custom_field)
74 @custom_values = @project.custom_values.find(:all, :include => :custom_field)
75 @members = @project.members.find(:all, :include => [:user, :role])
75 @members = @project.members.find(:all, :include => [:user, :role])
76 @subprojects = @project.children if @project.children_count > 0
76 @subprojects = @project.children if @project.children_count > 0
77 @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
77 @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
78 @trackers = Tracker.find(:all)
78 @trackers = Tracker.find(:all)
79 end
79 end
80
80
81 def settings
81 def settings
82 @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
82 @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
83 @custom_fields = IssueCustomField::find_all
83 @custom_fields = IssueCustomField::find_all
84 @issue_category ||= IssueCategory.new
84 @issue_category ||= IssueCategory.new
85 @member ||= @project.members.new
85 @member ||= @project.members.new
86 @roles = Role.find_all
86 @roles = Role.find_all
87 @users = User.find_all - @project.members.find(:all, :include => :user).collect{|m| m.user }
87 @users = User.find_all - @project.members.find(:all, :include => :user).collect{|m| m.user }
88 @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
88 @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
89 end
89 end
90
90
91 # Edit @project
91 # Edit @project
92 def edit
92 def edit
93 if request.post?
93 if request.post?
94 @project.custom_fields = IssueCustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
94 @project.custom_fields = IssueCustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
95 if params[:custom_fields]
95 if params[:custom_fields]
96 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
96 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
97 @project.custom_values = @custom_values
97 @project.custom_values = @custom_values
98 end
98 end
99 if @project.update_attributes(params[:project])
99 if @project.update_attributes(params[:project])
100 flash[:notice] = l(:notice_successful_update)
100 flash[:notice] = l(:notice_successful_update)
101 redirect_to :action => 'settings', :id => @project
101 redirect_to :action => 'settings', :id => @project
102 else
102 else
103 settings
103 settings
104 render :action => 'settings'
104 render :action => 'settings'
105 end
105 end
106 end
106 end
107 end
107 end
108
108
109 # Delete @project
109 # Delete @project
110 def destroy
110 def destroy
111 if request.post? and params[:confirm]
111 if request.post? and params[:confirm]
112 @project.destroy
112 @project.destroy
113 redirect_to :controller => 'admin', :action => 'projects'
113 redirect_to :controller => 'admin', :action => 'projects'
114 end
114 end
115 end
115 end
116
116
117 # Add a new issue category to @project
117 # Add a new issue category to @project
118 def add_issue_category
118 def add_issue_category
119 if request.post?
119 if request.post?
120 @issue_category = @project.issue_categories.build(params[:issue_category])
120 @issue_category = @project.issue_categories.build(params[:issue_category])
121 if @issue_category.save
121 if @issue_category.save
122 flash[:notice] = l(:notice_successful_create)
122 flash[:notice] = l(:notice_successful_create)
123 redirect_to :action => 'settings', :id => @project
123 redirect_to :action => 'settings', :id => @project
124 else
124 else
125 settings
125 settings
126 render :action => 'settings'
126 render :action => 'settings'
127 end
127 end
128 end
128 end
129 end
129 end
130
130
131 # Add a new version to @project
131 # Add a new version to @project
132 def add_version
132 def add_version
133 @version = @project.versions.build(params[:version])
133 @version = @project.versions.build(params[:version])
134 if request.post? and @version.save
134 if request.post? and @version.save
135 flash[:notice] = l(:notice_successful_create)
135 flash[:notice] = l(:notice_successful_create)
136 redirect_to :action => 'settings', :id => @project
136 redirect_to :action => 'settings', :id => @project
137 end
137 end
138 end
138 end
139
139
140 # Add a new member to @project
140 # Add a new member to @project
141 def add_member
141 def add_member
142 @member = @project.members.build(params[:member])
142 @member = @project.members.build(params[:member])
143 if request.post?
143 if request.post?
144 if @member.save
144 if @member.save
145 flash[:notice] = l(:notice_successful_create)
145 flash[:notice] = l(:notice_successful_create)
146 redirect_to :action => 'settings', :id => @project
146 redirect_to :action => 'settings', :id => @project
147 else
147 else
148 settings
148 settings
149 render :action => 'settings'
149 render :action => 'settings'
150 end
150 end
151 end
151 end
152 end
152 end
153
153
154 # Show members list of @project
154 # Show members list of @project
155 def list_members
155 def list_members
156 @members = @project.members
156 @members = @project.members
157 end
157 end
158
158
159 # Add a new document to @project
159 # Add a new document to @project
160 def add_document
160 def add_document
161 @categories = Enumeration::get_values('DCAT')
161 @categories = Enumeration::get_values('DCAT')
162 @document = @project.documents.build(params[:document])
162 @document = @project.documents.build(params[:document])
163 if request.post?
163 if request.post?
164 # Save the attachment
164 # Save the attachment
165 if params[:attachment][:file].size > 0
165 if params[:attachment][:file].size > 0
166 @attachment = @document.attachments.build(params[:attachment])
166 @attachment = @document.attachments.build(params[:attachment])
167 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
167 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
168 end
168 end
169 if @document.save
169 if @document.save
170 flash[:notice] = l(:notice_successful_create)
170 flash[:notice] = l(:notice_successful_create)
171 redirect_to :action => 'list_documents', :id => @project
171 redirect_to :action => 'list_documents', :id => @project
172 end
172 end
173 end
173 end
174 end
174 end
175
175
176 # Show documents list of @project
176 # Show documents list of @project
177 def list_documents
177 def list_documents
178 @documents = @project.documents
178 @documents = @project.documents.find :all, :include => :category
179 end
179 end
180
180
181 # Add a new issue to @project
181 # Add a new issue to @project
182 def add_issue
182 def add_issue
183 @tracker = Tracker.find(params[:tracker_id])
183 @tracker = Tracker.find(params[:tracker_id])
184 @priorities = Enumeration::get_values('IPRI')
184 @priorities = Enumeration::get_values('IPRI')
185 @issue = Issue.new(:project => @project, :tracker => @tracker)
185 @issue = Issue.new(:project => @project, :tracker => @tracker)
186 if request.get?
186 if request.get?
187 @issue.start_date = Date.today
187 @issue.start_date = Date.today
188 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
188 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
189 else
189 else
190 @issue.attributes = params[:issue]
190 @issue.attributes = params[:issue]
191 @issue.author_id = self.logged_in_user.id if self.logged_in_user
191 @issue.author_id = self.logged_in_user.id if self.logged_in_user
192 # Multiple file upload
192 # Multiple file upload
193 params[:attachments].each { |a|
193 params[:attachments].each { |a|
194 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
194 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
195 } if params[:attachments] and params[:attachments].is_a? Array
195 } if params[:attachments] and params[:attachments].is_a? Array
196 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
196 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
197 @issue.custom_values = @custom_values
197 @issue.custom_values = @custom_values
198 if @issue.save
198 if @issue.save
199 flash[:notice] = l(:notice_successful_create)
199 flash[:notice] = l(:notice_successful_create)
200 Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
200 Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
201 redirect_to :action => 'list_issues', :id => @project
201 redirect_to :action => 'list_issues', :id => @project
202 end
202 end
203 end
203 end
204 end
204 end
205
205
206 # Show filtered/sorted issues list of @project
206 # Show filtered/sorted issues list of @project
207 def list_issues
207 def list_issues
208 sort_init 'issues.id', 'desc'
208 sort_init 'issues.id', 'desc'
209 sort_update
209 sort_update
210
210
211 retrieve_query
211 retrieve_query
212
212
213 @results_per_page_options = [ 15, 25, 50, 100 ]
213 @results_per_page_options = [ 15, 25, 50, 100 ]
214 if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
214 if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
215 @results_per_page = params[:per_page].to_i
215 @results_per_page = params[:per_page].to_i
216 session[:results_per_page] = @results_per_page
216 session[:results_per_page] = @results_per_page
217 else
217 else
218 @results_per_page = session[:results_per_page] || 25
218 @results_per_page = session[:results_per_page] || 25
219 end
219 end
220
220
221 if @query.valid?
221 if @query.valid?
222 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
222 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
223 @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page']
223 @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page']
224 @issues = Issue.find :all, :order => sort_clause,
224 @issues = Issue.find :all, :order => sort_clause,
225 :include => [ :author, :status, :tracker, :project ],
225 :include => [ :author, :status, :tracker, :project ],
226 :conditions => @query.statement,
226 :conditions => @query.statement,
227 :limit => @issue_pages.items_per_page,
227 :limit => @issue_pages.items_per_page,
228 :offset => @issue_pages.current.offset
228 :offset => @issue_pages.current.offset
229 end
229 end
230 render :layout => false if request.xhr?
230 render :layout => false if request.xhr?
231 end
231 end
232
232
233 # Export filtered/sorted issues list to CSV
233 # Export filtered/sorted issues list to CSV
234 def export_issues_csv
234 def export_issues_csv
235 sort_init 'issues.id', 'desc'
235 sort_init 'issues.id', 'desc'
236 sort_update
236 sort_update
237
237
238 retrieve_query
238 retrieve_query
239 render :action => 'list_issues' and return unless @query.valid?
239 render :action => 'list_issues' and return unless @query.valid?
240
240
241 @issues = Issue.find :all, :order => sort_clause,
241 @issues = Issue.find :all, :order => sort_clause,
242 :include => [ :author, :status, :tracker, :project, :custom_values ],
242 :include => [ :author, :status, :tracker, :project, :custom_values ],
243 :conditions => @query.statement
243 :conditions => @query.statement
244
244
245 ic = Iconv.new('ISO-8859-1', 'UTF-8')
245 ic = Iconv.new('ISO-8859-1', 'UTF-8')
246 export = StringIO.new
246 export = StringIO.new
247 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
247 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
248 # csv header fields
248 # csv header fields
249 headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
249 headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
250 for custom_field in @project.all_custom_fields
250 for custom_field in @project.all_custom_fields
251 headers << custom_field.name
251 headers << custom_field.name
252 end
252 end
253 csv << headers.collect {|c| ic.iconv(c) }
253 csv << headers.collect {|c| ic.iconv(c) }
254 # csv lines
254 # csv lines
255 @issues.each do |issue|
255 @issues.each do |issue|
256 fields = [issue.id, issue.status.name, issue.tracker.name, issue.subject, issue.author.display_name, l_datetime(issue.created_on), l_datetime(issue.updated_on)]
256 fields = [issue.id, issue.status.name, issue.tracker.name, issue.subject, issue.author.display_name, l_datetime(issue.created_on), l_datetime(issue.updated_on)]
257 for custom_field in @project.all_custom_fields
257 for custom_field in @project.all_custom_fields
258 fields << (show_value issue.custom_value_for(custom_field))
258 fields << (show_value issue.custom_value_for(custom_field))
259 end
259 end
260 csv << fields.collect {|c| ic.iconv(c.to_s) }
260 csv << fields.collect {|c| ic.iconv(c.to_s) }
261 end
261 end
262 end
262 end
263 export.rewind
263 export.rewind
264 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
264 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
265 end
265 end
266
266
267 # Export filtered/sorted issues to PDF
267 # Export filtered/sorted issues to PDF
268 def export_issues_pdf
268 def export_issues_pdf
269 sort_init 'issues.id', 'desc'
269 sort_init 'issues.id', 'desc'
270 sort_update
270 sort_update
271
271
272 retrieve_query
272 retrieve_query
273 render :action => 'list_issues' and return unless @query.valid?
273 render :action => 'list_issues' and return unless @query.valid?
274
274
275 @issues = Issue.find :all, :order => sort_clause,
275 @issues = Issue.find :all, :order => sort_clause,
276 :include => [ :author, :status, :tracker, :project, :custom_values ],
276 :include => [ :author, :status, :tracker, :project, :custom_values ],
277 :conditions => @query.statement
277 :conditions => @query.statement
278
278
279 @options_for_rfpdf ||= {}
279 @options_for_rfpdf ||= {}
280 @options_for_rfpdf[:file_name] = "export.pdf"
280 @options_for_rfpdf[:file_name] = "export.pdf"
281 render :layout => false
281 render :layout => false
282 end
282 end
283
283
284 def move_issues
284 def move_issues
285 @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
285 @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
286 redirect_to :action => 'list_issues', :id => @project and return unless @issues
286 redirect_to :action => 'list_issues', :id => @project and return unless @issues
287 @projects = []
287 @projects = []
288 # find projects to which the user is allowed to move the issue
288 # find projects to which the user is allowed to move the issue
289 @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
289 @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
290 # issue can be moved to any tracker
290 # issue can be moved to any tracker
291 @trackers = Tracker.find(:all)
291 @trackers = Tracker.find(:all)
292 if request.post? and params[:new_project_id] and params[:new_tracker_id]
292 if request.post? and params[:new_project_id] and params[:new_tracker_id]
293 new_project = Project.find(params[:new_project_id])
293 new_project = Project.find(params[:new_project_id])
294 new_tracker = Tracker.find(params[:new_tracker_id])
294 new_tracker = Tracker.find(params[:new_tracker_id])
295 @issues.each { |i|
295 @issues.each { |i|
296 # category is project dependent
296 # category is project dependent
297 i.category = nil unless i.project_id == new_project.id
297 i.category = nil unless i.project_id == new_project.id
298 # move the issue
298 # move the issue
299 i.project = new_project
299 i.project = new_project
300 i.tracker = new_tracker
300 i.tracker = new_tracker
301 i.save
301 i.save
302 }
302 }
303 flash[:notice] = l(:notice_successful_update)
303 flash[:notice] = l(:notice_successful_update)
304 redirect_to :action => 'list_issues', :id => @project
304 redirect_to :action => 'list_issues', :id => @project
305 end
305 end
306 end
306 end
307
307
308 def add_query
308 def add_query
309 @query = Query.new(params[:query])
309 @query = Query.new(params[:query])
310 @query.project = @project
310 @query.project = @project
311 @query.user = logged_in_user
311 @query.user = logged_in_user
312
312
313 params[:fields].each do |field|
313 params[:fields].each do |field|
314 @query.add_filter(field, params[:operators][field], params[:values][field])
314 @query.add_filter(field, params[:operators][field], params[:values][field])
315 end if params[:fields]
315 end if params[:fields]
316
316
317 if request.post? and @query.save
317 if request.post? and @query.save
318 flash[:notice] = l(:notice_successful_create)
318 flash[:notice] = l(:notice_successful_create)
319 redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
319 redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
320 end
320 end
321 render :layout => false if request.xhr?
321 render :layout => false if request.xhr?
322 end
322 end
323
323
324 # Add a news to @project
324 # Add a news to @project
325 def add_news
325 def add_news
326 @news = News.new(:project => @project)
326 @news = News.new(:project => @project)
327 if request.post?
327 if request.post?
328 @news.attributes = params[:news]
328 @news.attributes = params[:news]
329 @news.author_id = self.logged_in_user.id if self.logged_in_user
329 @news.author_id = self.logged_in_user.id if self.logged_in_user
330 if @news.save
330 if @news.save
331 flash[:notice] = l(:notice_successful_create)
331 flash[:notice] = l(:notice_successful_create)
332 redirect_to :action => 'list_news', :id => @project
332 redirect_to :action => 'list_news', :id => @project
333 end
333 end
334 end
334 end
335 end
335 end
336
336
337 # Show news list of @project
337 # Show news list of @project
338 def list_news
338 def list_news
339 @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
339 @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
340 render :action => "list_news", :layout => false if request.xhr?
340 render :action => "list_news", :layout => false if request.xhr?
341 end
341 end
342
342
343 def add_file
343 def add_file
344 @attachment = Attachment.new(params[:attachment])
344 @attachment = Attachment.new(params[:attachment])
345 if request.post? and params[:attachment][:file].size > 0
345 if request.post? and params[:attachment][:file].size > 0
346 @attachment.container = @project.versions.find_by_id(params[:version_id])
346 @attachment.container = @project.versions.find_by_id(params[:version_id])
347 @attachment.author = logged_in_user
347 @attachment.author = logged_in_user
348 if @attachment.save
348 if @attachment.save
349 flash[:notice] = l(:notice_successful_create)
349 flash[:notice] = l(:notice_successful_create)
350 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
350 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
351 end
351 end
352 end
352 end
353 @versions = @project.versions
353 @versions = @project.versions
354 end
354 end
355
355
356 def list_files
356 def list_files
357 @versions = @project.versions
357 @versions = @project.versions
358 end
358 end
359
359
360 # Show changelog for @project
360 # Show changelog for @project
361 def changelog
361 def changelog
362 @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
362 @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
363 if request.get?
363 if request.get?
364 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
364 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
365 else
365 else
366 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
366 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
367 end
367 end
368 @selected_tracker_ids ||= []
368 @selected_tracker_ids ||= []
369 @fixed_issues = @project.issues.find(:all,
369 @fixed_issues = @project.issues.find(:all,
370 :include => [ :fixed_version, :status, :tracker ],
370 :include => [ :fixed_version, :status, :tracker ],
371 :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
371 :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
372 :order => "versions.effective_date DESC, issues.id DESC"
372 :order => "versions.effective_date DESC, issues.id DESC"
373 ) unless @selected_tracker_ids.empty?
373 ) unless @selected_tracker_ids.empty?
374 @fixed_issues ||= []
374 @fixed_issues ||= []
375 end
375 end
376
376
377 def activity
377 def activity
378 if params[:year] and params[:year].to_i > 1900
378 if params[:year] and params[:year].to_i > 1900
379 @year = params[:year].to_i
379 @year = params[:year].to_i
380 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
380 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
381 @month = params[:month].to_i
381 @month = params[:month].to_i
382 end
382 end
383 end
383 end
384 @year ||= Date.today.year
384 @year ||= Date.today.year
385 @month ||= Date.today.month
385 @month ||= Date.today.month
386
386
387 @date_from = Date.civil(@year, @month, 1)
387 @date_from = Date.civil(@year, @month, 1)
388 @date_to = (@date_from >> 1)-1
388 @date_to = (@date_from >> 1)-1
389
389
390 @events_by_day = {}
390 @events_by_day = {}
391
391
392 unless params[:show_issues] == "0"
392 unless params[:show_issues] == "0"
393 @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
393 @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
394 @events_by_day[i.created_on.to_date] ||= []
394 @events_by_day[i.created_on.to_date] ||= []
395 @events_by_day[i.created_on.to_date] << i
395 @events_by_day[i.created_on.to_date] << i
396 }
396 }
397 @show_issues = 1
397 @show_issues = 1
398 end
398 end
399
399
400 unless params[:show_news] == "0"
400 unless params[:show_news] == "0"
401 @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to] ).each { |i|
401 @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to], :include => :author ).each { |i|
402 @events_by_day[i.created_on.to_date] ||= []
402 @events_by_day[i.created_on.to_date] ||= []
403 @events_by_day[i.created_on.to_date] << i
403 @events_by_day[i.created_on.to_date] << i
404 }
404 }
405 @show_news = 1
405 @show_news = 1
406 end
406 end
407
407
408 unless params[:show_files] == "0"
408 unless params[:show_files] == "0"
409 Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN versions ON versions.id = attachments.container_id", :conditions => ["attachments.container_type='Version' and versions.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
409 Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN versions ON versions.id = attachments.container_id", :conditions => ["attachments.container_type='Version' and versions.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to], :include => :author ).each { |i|
410 @events_by_day[i.created_on.to_date] ||= []
410 @events_by_day[i.created_on.to_date] ||= []
411 @events_by_day[i.created_on.to_date] << i
411 @events_by_day[i.created_on.to_date] << i
412 }
412 }
413 @show_files = 1
413 @show_files = 1
414 end
414 end
415
415
416 unless params[:show_documents] == "0"
416 unless params[:show_documents] == "0"
417 @project.documents.find(:all, :conditions => ["documents.created_on>=? and documents.created_on<=?", @date_from, @date_to] ).each { |i|
417 @project.documents.find(:all, :conditions => ["documents.created_on>=? and documents.created_on<=?", @date_from, @date_to] ).each { |i|
418 @events_by_day[i.created_on.to_date] ||= []
418 @events_by_day[i.created_on.to_date] ||= []
419 @events_by_day[i.created_on.to_date] << i
419 @events_by_day[i.created_on.to_date] << i
420 }
420 }
421 Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN documents ON documents.id = attachments.container_id", :conditions => ["attachments.container_type='Document' and documents.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
421 Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN documents ON documents.id = attachments.container_id", :conditions => ["attachments.container_type='Document' and documents.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to], :include => :author ).each { |i|
422 @events_by_day[i.created_on.to_date] ||= []
422 @events_by_day[i.created_on.to_date] ||= []
423 @events_by_day[i.created_on.to_date] << i
423 @events_by_day[i.created_on.to_date] << i
424 }
424 }
425 @show_documents = 1
425 @show_documents = 1
426 end
426 end
427
427
428 render :layout => false if request.xhr?
428 render :layout => false if request.xhr?
429 end
429 end
430
430
431 def calendar
431 def calendar
432 if params[:year] and params[:year].to_i > 1900
432 if params[:year] and params[:year].to_i > 1900
433 @year = params[:year].to_i
433 @year = params[:year].to_i
434 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
434 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
435 @month = params[:month].to_i
435 @month = params[:month].to_i
436 end
436 end
437 end
437 end
438 @year ||= Date.today.year
438 @year ||= Date.today.year
439 @month ||= Date.today.month
439 @month ||= Date.today.month
440
440
441 @date_from = Date.civil(@year, @month, 1)
441 @date_from = Date.civil(@year, @month, 1)
442 @date_to = (@date_from >> 1)-1
442 @date_to = (@date_from >> 1)-1
443 # start on monday
443 # start on monday
444 @date_from = @date_from - (@date_from.cwday-1)
444 @date_from = @date_from - (@date_from.cwday-1)
445 # finish on sunday
445 # finish on sunday
446 @date_to = @date_to + (7-@date_to.cwday)
446 @date_to = @date_to + (7-@date_to.cwday)
447
447
448 @issues = @project.issues.find(:all, :include => :tracker, :conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to])
448 @issues = @project.issues.find(:all, :include => :tracker, :conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to])
449 render :layout => false if request.xhr?
449 render :layout => false if request.xhr?
450 end
450 end
451
451
452 def gantt
452 def gantt
453 if params[:year] and params[:year].to_i >0
453 if params[:year] and params[:year].to_i >0
454 @year_from = params[:year].to_i
454 @year_from = params[:year].to_i
455 if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
455 if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
456 @month_from = params[:month].to_i
456 @month_from = params[:month].to_i
457 else
457 else
458 @month_from = 1
458 @month_from = 1
459 end
459 end
460 else
460 else
461 @month_from ||= (Date.today << 1).month
461 @month_from ||= (Date.today << 1).month
462 @year_from ||= (Date.today << 1).year
462 @year_from ||= (Date.today << 1).year
463 end
463 end
464
464
465 @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
465 @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
466 @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
466 @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
467
467
468 @date_from = Date.civil(@year_from, @month_from, 1)
468 @date_from = Date.civil(@year_from, @month_from, 1)
469 @date_to = (@date_from >> @months) - 1
469 @date_to = (@date_from >> @months) - 1
470 @issues = @project.issues.find(:all, :order => "start_date, due_date", :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to])
470 @issues = @project.issues.find(:all, :order => "start_date, due_date", :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to])
471
471
472 if params[:output]=='pdf'
472 if params[:output]=='pdf'
473 @options_for_rfpdf ||= {}
473 @options_for_rfpdf ||= {}
474 @options_for_rfpdf[:file_name] = "gantt.pdf"
474 @options_for_rfpdf[:file_name] = "gantt.pdf"
475 render :template => "projects/gantt.rfpdf", :layout => false
475 render :template => "projects/gantt.rfpdf", :layout => false
476 else
476 else
477 render :template => "projects/gantt.rhtml"
477 render :template => "projects/gantt.rhtml"
478 end
478 end
479 end
479 end
480
480
481 private
481 private
482 # Find project of id params[:id]
482 # Find project of id params[:id]
483 # if not found, redirect to project list
483 # if not found, redirect to project list
484 # Used as a before_filter
484 # Used as a before_filter
485 def find_project
485 def find_project
486 @project = Project.find(params[:id])
486 @project = Project.find(params[:id])
487 @html_title = @project.name
487 @html_title = @project.name
488 rescue
488 rescue
489 redirect_to :action => 'list'
489 redirect_to :action => 'list'
490 end
490 end
491
491
492 # Retrieve query from session or build a new query
492 # Retrieve query from session or build a new query
493 def retrieve_query
493 def retrieve_query
494 if params[:query_id]
494 if params[:query_id]
495 @query = @project.queries.find(params[:query_id])
495 @query = @project.queries.find(params[:query_id])
496 else
496 else
497 if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
497 if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
498 # Give it a name, required to be valid
498 # Give it a name, required to be valid
499 @query = Query.new(:name => "_")
499 @query = Query.new(:name => "_")
500 @query.project = @project
500 @query.project = @project
501 if params[:fields] and params[:fields].is_a? Array
501 if params[:fields] and params[:fields].is_a? Array
502 params[:fields].each do |field|
502 params[:fields].each do |field|
503 @query.add_filter(field, params[:operators][field], params[:values][field])
503 @query.add_filter(field, params[:operators][field], params[:values][field])
504 end
504 end
505 else
505 else
506 @query.available_filters.keys.each do |field|
506 @query.available_filters.keys.each do |field|
507 @query.add_short_filter(field, params[field]) if params[field]
507 @query.add_short_filter(field, params[field]) if params[field]
508 end
508 end
509 end
509 end
510 session[:query] = @query
510 session[:query] = @query
511 else
511 else
512 @query = session[:query]
512 @query = session[:query]
513 end
513 end
514 end
514 end
515 end
515 end
516 end
516 end
@@ -1,58 +1,58
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 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 Project < ActiveRecord::Base
18 class Project < ActiveRecord::Base
19 has_many :versions, :dependent => true, :order => "versions.effective_date DESC, versions.name DESC"
19 has_many :versions, :dependent => true, :order => "versions.effective_date DESC, versions.name DESC"
20 has_many :members, :dependent => true
20 has_many :members, :dependent => true
21 has_many :users, :through => :members
21 has_many :users, :through => :members
22 has_many :custom_values, :dependent => true, :as => :customized
22 has_many :custom_values, :dependent => true, :as => :customized
23 has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => :status
23 has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => [:status, :tracker]
24 has_many :queries, :dependent => true
24 has_many :queries, :dependent => true
25 has_many :documents, :dependent => true
25 has_many :documents, :dependent => true
26 has_many :news, :dependent => true, :include => :author
26 has_many :news, :dependent => true, :include => :author
27 has_many :issue_categories, :dependent => true, :order => "issue_categories.name"
27 has_many :issue_categories, :dependent => true, :order => "issue_categories.name"
28 has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_projects', :association_foreign_key => 'custom_field_id'
28 has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_projects', :association_foreign_key => 'custom_field_id'
29 acts_as_tree :order => "name", :counter_cache => true
29 acts_as_tree :order => "name", :counter_cache => true
30
30
31 validates_presence_of :name, :description
31 validates_presence_of :name, :description
32 validates_uniqueness_of :name
32 validates_uniqueness_of :name
33 validates_associated :custom_values, :on => :update
33 validates_associated :custom_values, :on => :update
34
34
35 # returns 5 last created projects
35 # returns 5 last created projects
36 def self.latest
36 def self.latest
37 find(:all, :limit => 5, :order => "created_on DESC")
37 find(:all, :limit => 5, :order => "created_on DESC")
38 end
38 end
39
39
40 # Returns an array of all custom fields enabled for project issues
40 # Returns an array of all custom fields enabled for project issues
41 # (explictly associated custom fields and custom fields enabled for all projects)
41 # (explictly associated custom fields and custom fields enabled for all projects)
42 def custom_fields_for_issues(tracker)
42 def custom_fields_for_issues(tracker)
43 tracker.custom_fields.find(:all, :include => :projects,
43 tracker.custom_fields.find(:all, :include => :projects,
44 :conditions => ["is_for_all=? or project_id=?", true, self.id])
44 :conditions => ["is_for_all=? or project_id=?", true, self.id])
45 #(CustomField.for_all + custom_fields).uniq
45 #(CustomField.for_all + custom_fields).uniq
46 end
46 end
47
47
48 def all_custom_fields
48 def all_custom_fields
49 @all_custom_fields ||= IssueCustomField.find(:all, :include => :projects,
49 @all_custom_fields ||= IssueCustomField.find(:all, :include => :projects,
50 :conditions => ["is_for_all=? or project_id=?", true, self.id])
50 :conditions => ["is_for_all=? or project_id=?", true, self.id])
51 end
51 end
52
52
53 protected
53 protected
54 def validate
54 def validate
55 errors.add(parent_id, " must be a root project") if parent and parent.parent
55 errors.add(parent_id, " must be a root project") if parent and parent.parent
56 errors.add_to_base("A project with subprojects can't be a subproject") if parent and projects_count > 0
56 errors.add_to_base("A project with subprojects can't be a subproject") if parent and projects_count > 0
57 end
57 end
58 end
58 end
General Comments 0
You need to be logged in to leave comments. Login now