##// END OF EJS Templates
ActiveRecord::RecordNotFound exceptions handled more gracefully...
Jean-Philippe Lang -
r130:e3becc7c3c53
parent child
Show More
@@ -0,0 +1,4
1 <h2>404</h2>
2
3 <p><%= l(:notice_file_not_found) %></p>
4 <p><a href="javascript:history.back()">Back</a></p>
@@ -1,131 +1,133
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 AccountController < ApplicationController
18 class AccountController < ApplicationController
19 layout 'base'
19 layout 'base'
20 helper :custom_fields
20 helper :custom_fields
21 include CustomFieldsHelper
21 include CustomFieldsHelper
22
22
23 # prevents login action to be filtered by check_if_login_required application scope filter
23 # prevents login action to be filtered by check_if_login_required application scope filter
24 skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
24 skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
25 before_filter :require_login, :except => [:show, :login, :lost_password, :register]
25 before_filter :require_login, :except => [:show, :login, :lost_password, :register]
26
26
27 # Show user's account
27 # Show user's account
28 def show
28 def show
29 @user = User.find(params[:id])
29 @user = User.find(params[:id])
30 @custom_values = @user.custom_values.find(:all, :include => :custom_field)
30 @custom_values = @user.custom_values.find(:all, :include => :custom_field)
31 rescue ActiveRecord::RecordNotFound
32 render_404
31 end
33 end
32
34
33 # Login request and validation
35 # Login request and validation
34 def login
36 def login
35 if request.get?
37 if request.get?
36 # Logout user
38 # Logout user
37 self.logged_in_user = nil
39 self.logged_in_user = nil
38 else
40 else
39 # Authenticate user
41 # Authenticate user
40 user = User.try_to_login(params[:login], params[:password])
42 user = User.try_to_login(params[:login], params[:password])
41 if user
43 if user
42 self.logged_in_user = user
44 self.logged_in_user = user
43 redirect_back_or_default :controller => 'my', :action => 'page'
45 redirect_back_or_default :controller => 'my', :action => 'page'
44 else
46 else
45 flash.now[:notice] = l(:notice_account_invalid_creditentials)
47 flash.now[:notice] = l(:notice_account_invalid_creditentials)
46 end
48 end
47 end
49 end
48 end
50 end
49
51
50 # Log out current user and redirect to welcome page
52 # Log out current user and redirect to welcome page
51 def logout
53 def logout
52 self.logged_in_user = nil
54 self.logged_in_user = nil
53 redirect_to :controller => ''
55 redirect_to :controller => ''
54 end
56 end
55
57
56 # Enable user to choose a new password
58 # Enable user to choose a new password
57 def lost_password
59 def lost_password
58 if params[:token]
60 if params[:token]
59 @token = Token.find_by_action_and_value("recovery", params[:token])
61 @token = Token.find_by_action_and_value("recovery", params[:token])
60 redirect_to :controller => '' and return unless @token and !@token.expired?
62 redirect_to :controller => '' and return unless @token and !@token.expired?
61 @user = @token.user
63 @user = @token.user
62 if request.post?
64 if request.post?
63 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
65 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
64 if @user.save
66 if @user.save
65 @token.destroy
67 @token.destroy
66 flash[:notice] = l(:notice_account_password_updated)
68 flash[:notice] = l(:notice_account_password_updated)
67 redirect_to :action => 'login'
69 redirect_to :action => 'login'
68 return
70 return
69 end
71 end
70 end
72 end
71 render :template => "account/password_recovery"
73 render :template => "account/password_recovery"
72 return
74 return
73 else
75 else
74 if request.post?
76 if request.post?
75 user = User.find_by_mail(params[:mail])
77 user = User.find_by_mail(params[:mail])
76 # user not found in db
78 # user not found in db
77 flash.now[:notice] = l(:notice_account_unknown_email) and return unless user
79 flash.now[:notice] = l(:notice_account_unknown_email) and return unless user
78 # user uses an external authentification
80 # user uses an external authentification
79 flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id
81 flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id
80 # create a new token for password recovery
82 # create a new token for password recovery
81 token = Token.new(:user => user, :action => "recovery")
83 token = Token.new(:user => user, :action => "recovery")
82 if token.save
84 if token.save
83 # send token to user via email
85 # send token to user via email
84 Mailer.set_language_if_valid(user.language)
86 Mailer.set_language_if_valid(user.language)
85 Mailer.deliver_lost_password(token)
87 Mailer.deliver_lost_password(token)
86 flash[:notice] = l(:notice_account_lost_email_sent)
88 flash[:notice] = l(:notice_account_lost_email_sent)
87 redirect_to :action => 'login'
89 redirect_to :action => 'login'
88 return
90 return
89 end
91 end
90 end
92 end
91 end
93 end
92 end
94 end
93
95
94 # User self-registration
96 # User self-registration
95 def register
97 def register
96 redirect_to :controller => '' and return if $RDM_SELF_REGISTRATION == false
98 redirect_to :controller => '' and return if $RDM_SELF_REGISTRATION == false
97 if params[:token]
99 if params[:token]
98 token = Token.find_by_action_and_value("register", params[:token])
100 token = Token.find_by_action_and_value("register", params[:token])
99 redirect_to :controller => '' and return unless token and !token.expired?
101 redirect_to :controller => '' and return unless token and !token.expired?
100 user = token.user
102 user = token.user
101 redirect_to :controller => '' and return unless user.status == User::STATUS_REGISTERED
103 redirect_to :controller => '' and return unless user.status == User::STATUS_REGISTERED
102 user.status = User::STATUS_ACTIVE
104 user.status = User::STATUS_ACTIVE
103 if user.save
105 if user.save
104 token.destroy
106 token.destroy
105 flash[:notice] = l(:notice_account_activated)
107 flash[:notice] = l(:notice_account_activated)
106 redirect_to :action => 'login'
108 redirect_to :action => 'login'
107 return
109 return
108 end
110 end
109 else
111 else
110 if request.get?
112 if request.get?
111 @user = User.new(:language => $RDM_DEFAULT_LANG)
113 @user = User.new(:language => $RDM_DEFAULT_LANG)
112 @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
114 @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
113 else
115 else
114 @user = User.new(params[:user])
116 @user = User.new(params[:user])
115 @user.admin = false
117 @user.admin = false
116 @user.login = params[:user][:login]
118 @user.login = params[:user][:login]
117 @user.status = User::STATUS_REGISTERED
119 @user.status = User::STATUS_REGISTERED
118 @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
120 @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
119 @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
121 @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
120 @user.custom_values = @custom_values
122 @user.custom_values = @custom_values
121 token = Token.new(:user => @user, :action => "register")
123 token = Token.new(:user => @user, :action => "register")
122 if @user.save and token.save
124 if @user.save and token.save
123 Mailer.set_language_if_valid(@user.language)
125 Mailer.set_language_if_valid(@user.language)
124 Mailer.deliver_register(token)
126 Mailer.deliver_register(token)
125 flash[:notice] = l(:notice_account_register_done)
127 flash[:notice] = l(:notice_account_register_done)
126 redirect_to :controller => ''
128 redirect_to :controller => ''
127 end
129 end
128 end
130 end
129 end
131 end
130 end
132 end
131 end
133 end
@@ -1,126 +1,132
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])
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
107
108 def render_404
109 @html_title = "404"
110 render :template => "common/404", :layout => true, :status => 404
111 return false
106 end
112 end
107
113
108 # qvalues http header parser
114 # qvalues http header parser
109 # code taken from webrick
115 # code taken from webrick
110 def parse_qvalues(value)
116 def parse_qvalues(value)
111 tmp = []
117 tmp = []
112 if value
118 if value
113 parts = value.split(/,\s*/)
119 parts = value.split(/,\s*/)
114 parts.each {|part|
120 parts.each {|part|
115 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
121 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
116 val = m[1]
122 val = m[1]
117 q = (m[2] or 1).to_f
123 q = (m[2] or 1).to_f
118 tmp.push([val, q])
124 tmp.push([val, q])
119 end
125 end
120 }
126 }
121 tmp = tmp.sort_by{|val, q| -q}
127 tmp = tmp.sort_by{|val, q| -q}
122 tmp.collect!{|val, q| val}
128 tmp.collect!{|val, q| val}
123 end
129 end
124 return tmp
130 return tmp
125 end
131 end
126 end No newline at end of file
132 end
@@ -1,66 +1,67
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 DocumentsController < ApplicationController
18 class DocumentsController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def show
22 def show
23 @attachments = @document.attachments.find(:all, :order => "created_on DESC")
23 @attachments = @document.attachments.find(:all, :order => "created_on DESC")
24 end
24 end
25
25
26 def edit
26 def edit
27 @categories = Enumeration::get_values('DCAT')
27 @categories = Enumeration::get_values('DCAT')
28 if request.post? and @document.update_attributes(params[:document])
28 if request.post? and @document.update_attributes(params[:document])
29 flash[:notice] = l(:notice_successful_update)
29 flash[:notice] = l(:notice_successful_update)
30 redirect_to :action => 'show', :id => @document
30 redirect_to :action => 'show', :id => @document
31 end
31 end
32 end
32 end
33
33
34 def destroy
34 def destroy
35 @document.destroy
35 @document.destroy
36 redirect_to :controller => 'projects', :action => 'list_documents', :id => @project
36 redirect_to :controller => 'projects', :action => 'list_documents', :id => @project
37 end
37 end
38
38
39 def download
39 def download
40 @attachment = @document.attachments.find(params[:attachment_id])
40 @attachment = @document.attachments.find(params[:attachment_id])
41 @attachment.increment_download
41 @attachment.increment_download
42 send_file @attachment.diskfile, :filename => @attachment.filename
42 send_file @attachment.diskfile, :filename => @attachment.filename
43 rescue
43 rescue
44 flash.now[:notice] = l(:notice_file_not_found)
44 render_404
45 render :text => "", :layout => true, :status => 404
46 end
45 end
47
46
48 def add_attachment
47 def add_attachment
49 # Save the attachments
48 # Save the attachments
50 params[:attachments].each { |a|
49 params[:attachments].each { |a|
51 Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
50 Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
52 } if params[:attachments] and params[:attachments].is_a? Array
51 } if params[:attachments] and params[:attachments].is_a? Array
53 redirect_to :action => 'show', :id => @document
52 redirect_to :action => 'show', :id => @document
54 end
53 end
55
54
56 def destroy_attachment
55 def destroy_attachment
57 @document.attachments.find(params[:attachment_id]).destroy
56 @document.attachments.find(params[:attachment_id]).destroy
58 redirect_to :action => 'show', :id => @document
57 redirect_to :action => 'show', :id => @document
59 end
58 end
60
59
61 private
60 private
62 def find_project
61 def find_project
63 @document = Document.find(params[:id])
62 @document = Document.find(params[:id])
64 @project = @document.project
63 @project = @document.project
64 rescue ActiveRecord::RecordNotFound
65 render_404
65 end
66 end
66 end
67 end
@@ -1,42 +1,44
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 IssueCategoriesController < ApplicationController
18 class IssueCategoriesController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def edit
22 def edit
23 if request.post? and @category.update_attributes(params[:category])
23 if request.post? and @category.update_attributes(params[:category])
24 flash[:notice] = l(:notice_successful_update)
24 flash[:notice] = l(:notice_successful_update)
25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
26 end
26 end
27 end
27 end
28
28
29 def destroy
29 def destroy
30 @category.destroy
30 @category.destroy
31 redirect_to :controller => 'projects', :action => 'settings', :id => @project
31 redirect_to :controller => 'projects', :action => 'settings', :id => @project
32 rescue
32 rescue
33 flash[:notice] = "Categorie can't be deleted"
33 flash[:notice] = "Categorie can't be deleted"
34 redirect_to :controller => 'projects', :action => 'settings', :id => @project
34 redirect_to :controller => 'projects', :action => 'settings', :id => @project
35 end
35 end
36
36
37 private
37 private
38 def find_project
38 def find_project
39 @category = IssueCategory.find(params[:id])
39 @category = IssueCategory.find(params[:id])
40 @project = @category.project
40 @project = @category.project
41 end
41 rescue ActiveRecord::RecordNotFound
42 render_404
43 end
42 end
44 end
@@ -1,145 +1,146
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 IssuesController < ApplicationController
18 class IssuesController < ApplicationController
19 layout 'base', :except => :export_pdf
19 layout 'base', :except => :export_pdf
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 helper :custom_fields
22 helper :custom_fields
23 include CustomFieldsHelper
23 include CustomFieldsHelper
24 helper :ifpdf
24 helper :ifpdf
25 include IfpdfHelper
25 include IfpdfHelper
26
26
27 def show
27 def show
28 @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
28 @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
29 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
29 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
30 @journals_count = @issue.journals.count
30 @journals_count = @issue.journals.count
31 @journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc")
31 @journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc")
32 end
32 end
33
33
34 def history
34 def history
35 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "journals.created_on desc")
35 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "journals.created_on desc")
36 @journals_count = @journals.length
36 @journals_count = @journals.length
37 end
37 end
38
38
39 def export_pdf
39 def export_pdf
40 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
40 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
41 @options_for_rfpdf ||= {}
41 @options_for_rfpdf ||= {}
42 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
42 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
43 end
43 end
44
44
45 def edit
45 def edit
46 @priorities = Enumeration::get_values('IPRI')
46 @priorities = Enumeration::get_values('IPRI')
47 if request.get?
47 if request.get?
48 @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
48 @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
49 else
49 else
50 begin
50 begin
51 @issue.init_journal(self.logged_in_user)
51 @issue.init_journal(self.logged_in_user)
52 # Retrieve custom fields and values
52 # Retrieve custom fields and values
53 @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
53 @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
54 @issue.custom_values = @custom_values
54 @issue.custom_values = @custom_values
55 @issue.attributes = params[:issue]
55 @issue.attributes = params[:issue]
56 if @issue.save
56 if @issue.save
57 flash[:notice] = l(:notice_successful_update)
57 flash[:notice] = l(:notice_successful_update)
58 redirect_to :action => 'show', :id => @issue
58 redirect_to :action => 'show', :id => @issue
59 end
59 end
60 rescue ActiveRecord::StaleObjectError
60 rescue ActiveRecord::StaleObjectError
61 # Optimistic locking exception
61 # Optimistic locking exception
62 flash[:notice] = l(:notice_locking_conflict)
62 flash[:notice] = l(:notice_locking_conflict)
63 end
63 end
64 end
64 end
65 end
65 end
66
66
67 def add_note
67 def add_note
68 unless params[:notes].empty?
68 unless params[:notes].empty?
69 journal = @issue.init_journal(self.logged_in_user, params[:notes])
69 journal = @issue.init_journal(self.logged_in_user, params[:notes])
70 #@history = @issue.histories.build(params[:history])
70 #@history = @issue.histories.build(params[:history])
71 #@history.author_id = self.logged_in_user.id if self.logged_in_user
71 #@history.author_id = self.logged_in_user.id if self.logged_in_user
72 #@history.status = @issue.status
72 #@history.status = @issue.status
73 if @issue.save
73 if @issue.save
74 flash[:notice] = l(:notice_successful_update)
74 flash[:notice] = l(:notice_successful_update)
75 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
75 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
76 redirect_to :action => 'show', :id => @issue
76 redirect_to :action => 'show', :id => @issue
77 return
77 return
78 end
78 end
79 end
79 end
80 show
80 show
81 render :action => 'show'
81 render :action => 'show'
82 end
82 end
83
83
84 def change_status
84 def change_status
85 #@history = @issue.histories.build(params[:history])
85 #@history = @issue.histories.build(params[:history])
86 @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
86 @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
87 @new_status = IssueStatus.find(params[:new_status_id])
87 @new_status = IssueStatus.find(params[:new_status_id])
88 if params[:confirm]
88 if params[:confirm]
89 begin
89 begin
90 #@history.author_id = self.logged_in_user.id if self.logged_in_user
90 #@history.author_id = self.logged_in_user.id if self.logged_in_user
91 #@issue.status = @history.status
91 #@issue.status = @history.status
92 #@issue.fixed_version_id = (params[:issue][:fixed_version_id])
92 #@issue.fixed_version_id = (params[:issue][:fixed_version_id])
93 #@issue.assigned_to_id = (params[:issue][:assigned_to_id])
93 #@issue.assigned_to_id = (params[:issue][:assigned_to_id])
94 #@issue.done_ratio = (params[:issue][:done_ratio])
94 #@issue.done_ratio = (params[:issue][:done_ratio])
95 #@issue.lock_version = (params[:issue][:lock_version])
95 #@issue.lock_version = (params[:issue][:lock_version])
96 journal = @issue.init_journal(self.logged_in_user, params[:notes])
96 journal = @issue.init_journal(self.logged_in_user, params[:notes])
97 @issue.status = @new_status
97 @issue.status = @new_status
98 if @issue.update_attributes(params[:issue])
98 if @issue.update_attributes(params[:issue])
99 flash[:notice] = l(:notice_successful_update)
99 flash[:notice] = l(:notice_successful_update)
100 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
100 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
101 redirect_to :action => 'show', :id => @issue
101 redirect_to :action => 'show', :id => @issue
102 end
102 end
103 rescue ActiveRecord::StaleObjectError
103 rescue ActiveRecord::StaleObjectError
104 # Optimistic locking exception
104 # Optimistic locking exception
105 flash[:notice] = l(:notice_locking_conflict)
105 flash[:notice] = l(:notice_locking_conflict)
106 end
106 end
107 end
107 end
108 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
108 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
109 end
109 end
110
110
111 def destroy
111 def destroy
112 @issue.destroy
112 @issue.destroy
113 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
113 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
114 end
114 end
115
115
116 def add_attachment
116 def add_attachment
117 # Save the attachments
117 # Save the attachments
118 params[:attachments].each { |a|
118 params[:attachments].each { |a|
119 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
119 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
120 @attachment.save
120 @attachment.save
121 } if params[:attachments] and params[:attachments].is_a? Array
121 } if params[:attachments] and params[:attachments].is_a? Array
122 redirect_to :action => 'show', :id => @issue
122 redirect_to :action => 'show', :id => @issue
123 end
123 end
124
124
125 def destroy_attachment
125 def destroy_attachment
126 @issue.attachments.find(params[:attachment_id]).destroy
126 @issue.attachments.find(params[:attachment_id]).destroy
127 redirect_to :action => 'show', :id => @issue
127 redirect_to :action => 'show', :id => @issue
128 end
128 end
129
129
130 # Send the file in stream mode
130 # Send the file in stream mode
131 def download
131 def download
132 @attachment = @issue.attachments.find(params[:attachment_id])
132 @attachment = @issue.attachments.find(params[:attachment_id])
133 send_file @attachment.diskfile, :filename => @attachment.filename
133 send_file @attachment.diskfile, :filename => @attachment.filename
134 rescue
134 rescue
135 flash.now[:notice] = l(:notice_file_not_found)
135 render_404
136 render :text => "", :layout => true, :status => 404
137 end
136 end
138
137
139 private
138 private
140 def find_project
139 def find_project
141 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
140 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
142 @project = @issue.project
141 @project = @issue.project
143 @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
142 @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
143 rescue ActiveRecord::RecordNotFound
144 render_404
144 end
145 end
145 end
146 end
@@ -1,41 +1,43
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 MembersController < ApplicationController
18 class MembersController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def edit
22 def edit
23 if request.post? and @member.update_attributes(params[:member])
23 if request.post? and @member.update_attributes(params[:member])
24 flash[:notice] = l(:notice_successful_update)
24 flash[:notice] = l(:notice_successful_update)
25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
26 end
26 end
27 end
27 end
28
28
29 def destroy
29 def destroy
30 @member.destroy
30 @member.destroy
31 flash[:notice] = l(:notice_successful_delete)
31 flash[:notice] = l(:notice_successful_delete)
32 redirect_to :controller => 'projects', :action => 'settings', :id => @project
32 redirect_to :controller => 'projects', :action => 'settings', :id => @project
33 end
33 end
34
34
35 private
35 private
36 def find_project
36 def find_project
37 @member = Member.find(params[:id])
37 @member = Member.find(params[:id])
38 @project = @member.project
38 @project = @member.project
39 end
39 rescue ActiveRecord::RecordNotFound
40 render_404
41 end
40
42
41 end
43 end
@@ -1,58 +1,60
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 NewsController < ApplicationController
18 class NewsController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def show
22 def show
23 end
23 end
24
24
25 def edit
25 def edit
26 if request.post? and @news.update_attributes(params[:news])
26 if request.post? and @news.update_attributes(params[:news])
27 flash[:notice] = l(:notice_successful_update)
27 flash[:notice] = l(:notice_successful_update)
28 redirect_to :action => 'show', :id => @news
28 redirect_to :action => 'show', :id => @news
29 end
29 end
30 end
30 end
31
31
32 def add_comment
32 def add_comment
33 @comment = Comment.new(params[:comment])
33 @comment = Comment.new(params[:comment])
34 @comment.author = logged_in_user
34 @comment.author = logged_in_user
35 if @news.comments << @comment
35 if @news.comments << @comment
36 flash[:notice] = l(:label_comment_added)
36 flash[:notice] = l(:label_comment_added)
37 redirect_to :action => 'show', :id => @news
37 redirect_to :action => 'show', :id => @news
38 else
38 else
39 render :action => 'show'
39 render :action => 'show'
40 end
40 end
41 end
41 end
42
42
43 def destroy_comment
43 def destroy_comment
44 @news.comments.find(params[:comment_id]).destroy
44 @news.comments.find(params[:comment_id]).destroy
45 redirect_to :action => 'show', :id => @news
45 redirect_to :action => 'show', :id => @news
46 end
46 end
47
47
48 def destroy
48 def destroy
49 @news.destroy
49 @news.destroy
50 redirect_to :controller => 'projects', :action => 'list_news', :id => @project
50 redirect_to :controller => 'projects', :action => 'list_news', :id => @project
51 end
51 end
52
52
53 private
53 private
54 def find_project
54 def find_project
55 @news = News.find(params[:id])
55 @news = News.find(params[:id])
56 @project = @news.project
56 @project = @news.project
57 end
57 rescue ActiveRecord::RecordNotFound
58 render_404
59 end
58 end
60 end
@@ -1,531 +1,531
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 params[:repository_enabled] && params[:repository_enabled] == "1"
65 if params[:repository_enabled] && params[:repository_enabled] == "1"
66 @project.repository = Repository.new
66 @project.repository = Repository.new
67 @project.repository.attributes = params[:repository]
67 @project.repository.attributes = params[:repository]
68 end
68 end
69 if @project.save
69 if @project.save
70 flash[:notice] = l(:notice_successful_create)
70 flash[:notice] = l(:notice_successful_create)
71 redirect_to :controller => 'admin', :action => 'projects'
71 redirect_to :controller => 'admin', :action => 'projects'
72 end
72 end
73 end
73 end
74 end
74 end
75
75
76 # Show @project
76 # Show @project
77 def show
77 def show
78 @custom_values = @project.custom_values.find(:all, :include => :custom_field)
78 @custom_values = @project.custom_values.find(:all, :include => :custom_field)
79 @members = @project.members.find(:all, :include => [:user, :role])
79 @members = @project.members.find(:all, :include => [:user, :role])
80 @subprojects = @project.children if @project.children_count > 0
80 @subprojects = @project.children if @project.children_count > 0
81 @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
81 @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
82 @trackers = Tracker.find(:all)
82 @trackers = Tracker.find(:all)
83 end
83 end
84
84
85 def settings
85 def settings
86 @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
86 @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
87 @custom_fields = IssueCustomField.find(:all)
87 @custom_fields = IssueCustomField.find(:all)
88 @issue_category ||= IssueCategory.new
88 @issue_category ||= IssueCategory.new
89 @member ||= @project.members.new
89 @member ||= @project.members.new
90 @roles = Role.find(:all)
90 @roles = Role.find(:all)
91 @users = User.find(:all) - @project.members.find(:all, :include => :user).collect{|m| m.user }
91 @users = User.find(:all) - @project.members.find(:all, :include => :user).collect{|m| m.user }
92 @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
92 @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
93 end
93 end
94
94
95 # Edit @project
95 # Edit @project
96 def edit
96 def edit
97 if request.post?
97 if request.post?
98 @project.custom_fields = IssueCustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
98 @project.custom_fields = IssueCustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
99 if params[:custom_fields]
99 if params[:custom_fields]
100 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
100 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
101 @project.custom_values = @custom_values
101 @project.custom_values = @custom_values
102 end
102 end
103 if params[:repository_enabled]
103 if params[:repository_enabled]
104 case params[:repository_enabled]
104 case params[:repository_enabled]
105 when "0"
105 when "0"
106 @project.repository = nil
106 @project.repository = nil
107 when "1"
107 when "1"
108 @project.repository ||= Repository.new
108 @project.repository ||= Repository.new
109 @project.repository.attributes = params[:repository]
109 @project.repository.attributes = params[:repository]
110 end
110 end
111 end
111 end
112 @project.attributes = params[:project]
112 @project.attributes = params[:project]
113 if @project.save
113 if @project.save
114 flash[:notice] = l(:notice_successful_update)
114 flash[:notice] = l(:notice_successful_update)
115 redirect_to :action => 'settings', :id => @project
115 redirect_to :action => 'settings', :id => @project
116 else
116 else
117 settings
117 settings
118 render :action => 'settings'
118 render :action => 'settings'
119 end
119 end
120 end
120 end
121 end
121 end
122
122
123 # Delete @project
123 # Delete @project
124 def destroy
124 def destroy
125 if request.post? and params[:confirm]
125 if request.post? and params[:confirm]
126 @project.destroy
126 @project.destroy
127 redirect_to :controller => 'admin', :action => 'projects'
127 redirect_to :controller => 'admin', :action => 'projects'
128 end
128 end
129 end
129 end
130
130
131 # Add a new issue category to @project
131 # Add a new issue category to @project
132 def add_issue_category
132 def add_issue_category
133 if request.post?
133 if request.post?
134 @issue_category = @project.issue_categories.build(params[:issue_category])
134 @issue_category = @project.issue_categories.build(params[:issue_category])
135 if @issue_category.save
135 if @issue_category.save
136 flash[:notice] = l(:notice_successful_create)
136 flash[:notice] = l(:notice_successful_create)
137 redirect_to :action => 'settings', :id => @project
137 redirect_to :action => 'settings', :id => @project
138 else
138 else
139 settings
139 settings
140 render :action => 'settings'
140 render :action => 'settings'
141 end
141 end
142 end
142 end
143 end
143 end
144
144
145 # Add a new version to @project
145 # Add a new version to @project
146 def add_version
146 def add_version
147 @version = @project.versions.build(params[:version])
147 @version = @project.versions.build(params[:version])
148 if request.post? and @version.save
148 if request.post? and @version.save
149 flash[:notice] = l(:notice_successful_create)
149 flash[:notice] = l(:notice_successful_create)
150 redirect_to :action => 'settings', :id => @project
150 redirect_to :action => 'settings', :id => @project
151 end
151 end
152 end
152 end
153
153
154 # Add a new member to @project
154 # Add a new member to @project
155 def add_member
155 def add_member
156 @member = @project.members.build(params[:member])
156 @member = @project.members.build(params[:member])
157 if request.post?
157 if request.post?
158 if @member.save
158 if @member.save
159 flash[:notice] = l(:notice_successful_create)
159 flash[:notice] = l(:notice_successful_create)
160 redirect_to :action => 'settings', :id => @project
160 redirect_to :action => 'settings', :id => @project
161 else
161 else
162 settings
162 settings
163 render :action => 'settings'
163 render :action => 'settings'
164 end
164 end
165 end
165 end
166 end
166 end
167
167
168 # Show members list of @project
168 # Show members list of @project
169 def list_members
169 def list_members
170 @members = @project.members
170 @members = @project.members
171 end
171 end
172
172
173 # Add a new document to @project
173 # Add a new document to @project
174 def add_document
174 def add_document
175 @categories = Enumeration::get_values('DCAT')
175 @categories = Enumeration::get_values('DCAT')
176 @document = @project.documents.build(params[:document])
176 @document = @project.documents.build(params[:document])
177 if request.post? and @document.save
177 if request.post? and @document.save
178 # Save the attachments
178 # Save the attachments
179 params[:attachments].each { |a|
179 params[:attachments].each { |a|
180 Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
180 Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
181 } if params[:attachments] and params[:attachments].is_a? Array
181 } if params[:attachments] and params[:attachments].is_a? Array
182 flash[:notice] = l(:notice_successful_create)
182 flash[:notice] = l(:notice_successful_create)
183 redirect_to :action => 'list_documents', :id => @project
183 redirect_to :action => 'list_documents', :id => @project
184 end
184 end
185 end
185 end
186
186
187 # Show documents list of @project
187 # Show documents list of @project
188 def list_documents
188 def list_documents
189 @documents = @project.documents.find :all, :include => :category
189 @documents = @project.documents.find :all, :include => :category
190 end
190 end
191
191
192 # Add a new issue to @project
192 # Add a new issue to @project
193 def add_issue
193 def add_issue
194 @tracker = Tracker.find(params[:tracker_id])
194 @tracker = Tracker.find(params[:tracker_id])
195 @priorities = Enumeration::get_values('IPRI')
195 @priorities = Enumeration::get_values('IPRI')
196 @issue = Issue.new(:project => @project, :tracker => @tracker)
196 @issue = Issue.new(:project => @project, :tracker => @tracker)
197 if request.get?
197 if request.get?
198 @issue.start_date = Date.today
198 @issue.start_date = Date.today
199 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
199 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
200 else
200 else
201 @issue.attributes = params[:issue]
201 @issue.attributes = params[:issue]
202 @issue.author_id = self.logged_in_user.id if self.logged_in_user
202 @issue.author_id = self.logged_in_user.id if self.logged_in_user
203 # Multiple file upload
203 # Multiple file upload
204 @attachments = []
204 @attachments = []
205 params[:attachments].each { |a|
205 params[:attachments].each { |a|
206 @attachments << Attachment.new(:container => @issue, :file => a, :author => logged_in_user) unless a.size == 0
206 @attachments << Attachment.new(:container => @issue, :file => a, :author => logged_in_user) unless a.size == 0
207 } if params[:attachments] and params[:attachments].is_a? Array
207 } if params[:attachments] and params[:attachments].is_a? Array
208 @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]) }
208 @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]) }
209 @issue.custom_values = @custom_values
209 @issue.custom_values = @custom_values
210 if @issue.save
210 if @issue.save
211 @attachments.each(&:save)
211 @attachments.each(&:save)
212 flash[:notice] = l(:notice_successful_create)
212 flash[:notice] = l(:notice_successful_create)
213 Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
213 Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
214 redirect_to :action => 'list_issues', :id => @project
214 redirect_to :action => 'list_issues', :id => @project
215 end
215 end
216 end
216 end
217 end
217 end
218
218
219 # Show filtered/sorted issues list of @project
219 # Show filtered/sorted issues list of @project
220 def list_issues
220 def list_issues
221 sort_init 'issues.id', 'desc'
221 sort_init 'issues.id', 'desc'
222 sort_update
222 sort_update
223
223
224 retrieve_query
224 retrieve_query
225
225
226 @results_per_page_options = [ 15, 25, 50, 100 ]
226 @results_per_page_options = [ 15, 25, 50, 100 ]
227 if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
227 if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
228 @results_per_page = params[:per_page].to_i
228 @results_per_page = params[:per_page].to_i
229 session[:results_per_page] = @results_per_page
229 session[:results_per_page] = @results_per_page
230 else
230 else
231 @results_per_page = session[:results_per_page] || 25
231 @results_per_page = session[:results_per_page] || 25
232 end
232 end
233
233
234 if @query.valid?
234 if @query.valid?
235 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
235 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
236 @issue_pages = Paginator.new self, @issue_count, @results_per_page, params['page']
236 @issue_pages = Paginator.new self, @issue_count, @results_per_page, params['page']
237 @issues = Issue.find :all, :order => sort_clause,
237 @issues = Issue.find :all, :order => sort_clause,
238 :include => [ :author, :status, :tracker, :project ],
238 :include => [ :author, :status, :tracker, :project ],
239 :conditions => @query.statement,
239 :conditions => @query.statement,
240 :limit => @issue_pages.items_per_page,
240 :limit => @issue_pages.items_per_page,
241 :offset => @issue_pages.current.offset
241 :offset => @issue_pages.current.offset
242 end
242 end
243 render :layout => false if request.xhr?
243 render :layout => false if request.xhr?
244 end
244 end
245
245
246 # Export filtered/sorted issues list to CSV
246 # Export filtered/sorted issues list to CSV
247 def export_issues_csv
247 def export_issues_csv
248 sort_init 'issues.id', 'desc'
248 sort_init 'issues.id', 'desc'
249 sort_update
249 sort_update
250
250
251 retrieve_query
251 retrieve_query
252 render :action => 'list_issues' and return unless @query.valid?
252 render :action => 'list_issues' and return unless @query.valid?
253
253
254 @issues = Issue.find :all, :order => sort_clause,
254 @issues = Issue.find :all, :order => sort_clause,
255 :include => [ :author, :status, :tracker, :project, :custom_values ],
255 :include => [ :author, :status, :tracker, :project, :custom_values ],
256 :conditions => @query.statement
256 :conditions => @query.statement
257
257
258 ic = Iconv.new('ISO-8859-1', 'UTF-8')
258 ic = Iconv.new('ISO-8859-1', 'UTF-8')
259 export = StringIO.new
259 export = StringIO.new
260 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
260 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
261 # csv header fields
261 # csv header fields
262 headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
262 headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
263 for custom_field in @project.all_custom_fields
263 for custom_field in @project.all_custom_fields
264 headers << custom_field.name
264 headers << custom_field.name
265 end
265 end
266 csv << headers.collect {|c| ic.iconv(c) }
266 csv << headers.collect {|c| ic.iconv(c) }
267 # csv lines
267 # csv lines
268 @issues.each do |issue|
268 @issues.each do |issue|
269 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)]
269 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)]
270 for custom_field in @project.all_custom_fields
270 for custom_field in @project.all_custom_fields
271 fields << (show_value issue.custom_value_for(custom_field))
271 fields << (show_value issue.custom_value_for(custom_field))
272 end
272 end
273 csv << fields.collect {|c| ic.iconv(c.to_s) }
273 csv << fields.collect {|c| ic.iconv(c.to_s) }
274 end
274 end
275 end
275 end
276 export.rewind
276 export.rewind
277 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
277 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
278 end
278 end
279
279
280 # Export filtered/sorted issues to PDF
280 # Export filtered/sorted issues to PDF
281 def export_issues_pdf
281 def export_issues_pdf
282 sort_init 'issues.id', 'desc'
282 sort_init 'issues.id', 'desc'
283 sort_update
283 sort_update
284
284
285 retrieve_query
285 retrieve_query
286 render :action => 'list_issues' and return unless @query.valid?
286 render :action => 'list_issues' and return unless @query.valid?
287
287
288 @issues = Issue.find :all, :order => sort_clause,
288 @issues = Issue.find :all, :order => sort_clause,
289 :include => [ :author, :status, :tracker, :project, :custom_values ],
289 :include => [ :author, :status, :tracker, :project, :custom_values ],
290 :conditions => @query.statement
290 :conditions => @query.statement
291
291
292 @options_for_rfpdf ||= {}
292 @options_for_rfpdf ||= {}
293 @options_for_rfpdf[:file_name] = "export.pdf"
293 @options_for_rfpdf[:file_name] = "export.pdf"
294 render :layout => false
294 render :layout => false
295 end
295 end
296
296
297 def move_issues
297 def move_issues
298 @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
298 @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
299 redirect_to :action => 'list_issues', :id => @project and return unless @issues
299 redirect_to :action => 'list_issues', :id => @project and return unless @issues
300 @projects = []
300 @projects = []
301 # find projects to which the user is allowed to move the issue
301 # find projects to which the user is allowed to move the issue
302 @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
302 @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
303 # issue can be moved to any tracker
303 # issue can be moved to any tracker
304 @trackers = Tracker.find(:all)
304 @trackers = Tracker.find(:all)
305 if request.post? and params[:new_project_id] and params[:new_tracker_id]
305 if request.post? and params[:new_project_id] and params[:new_tracker_id]
306 new_project = Project.find(params[:new_project_id])
306 new_project = Project.find(params[:new_project_id])
307 new_tracker = Tracker.find(params[:new_tracker_id])
307 new_tracker = Tracker.find(params[:new_tracker_id])
308 @issues.each { |i|
308 @issues.each { |i|
309 # project dependent properties
309 # project dependent properties
310 unless i.project_id == new_project.id
310 unless i.project_id == new_project.id
311 i.category = nil
311 i.category = nil
312 i.fixed_version = nil
312 i.fixed_version = nil
313 end
313 end
314 # move the issue
314 # move the issue
315 i.project = new_project
315 i.project = new_project
316 i.tracker = new_tracker
316 i.tracker = new_tracker
317 i.save
317 i.save
318 }
318 }
319 flash[:notice] = l(:notice_successful_update)
319 flash[:notice] = l(:notice_successful_update)
320 redirect_to :action => 'list_issues', :id => @project
320 redirect_to :action => 'list_issues', :id => @project
321 end
321 end
322 end
322 end
323
323
324 def add_query
324 def add_query
325 @query = Query.new(params[:query])
325 @query = Query.new(params[:query])
326 @query.project = @project
326 @query.project = @project
327 @query.user = logged_in_user
327 @query.user = logged_in_user
328
328
329 params[:fields].each do |field|
329 params[:fields].each do |field|
330 @query.add_filter(field, params[:operators][field], params[:values][field])
330 @query.add_filter(field, params[:operators][field], params[:values][field])
331 end if params[:fields]
331 end if params[:fields]
332
332
333 if request.post? and @query.save
333 if request.post? and @query.save
334 flash[:notice] = l(:notice_successful_create)
334 flash[:notice] = l(:notice_successful_create)
335 redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
335 redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
336 end
336 end
337 render :layout => false if request.xhr?
337 render :layout => false if request.xhr?
338 end
338 end
339
339
340 # Add a news to @project
340 # Add a news to @project
341 def add_news
341 def add_news
342 @news = News.new(:project => @project)
342 @news = News.new(:project => @project)
343 if request.post?
343 if request.post?
344 @news.attributes = params[:news]
344 @news.attributes = params[:news]
345 @news.author_id = self.logged_in_user.id if self.logged_in_user
345 @news.author_id = self.logged_in_user.id if self.logged_in_user
346 if @news.save
346 if @news.save
347 flash[:notice] = l(:notice_successful_create)
347 flash[:notice] = l(:notice_successful_create)
348 redirect_to :action => 'list_news', :id => @project
348 redirect_to :action => 'list_news', :id => @project
349 end
349 end
350 end
350 end
351 end
351 end
352
352
353 # Show news list of @project
353 # Show news list of @project
354 def list_news
354 def list_news
355 @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
355 @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
356 render :action => "list_news", :layout => false if request.xhr?
356 render :action => "list_news", :layout => false if request.xhr?
357 end
357 end
358
358
359 def add_file
359 def add_file
360 if request.post?
360 if request.post?
361 @version = @project.versions.find_by_id(params[:version_id])
361 @version = @project.versions.find_by_id(params[:version_id])
362 # Save the attachments
362 # Save the attachments
363 params[:attachments].each { |a|
363 params[:attachments].each { |a|
364 Attachment.create(:container => @version, :file => a, :author => logged_in_user) unless a.size == 0
364 Attachment.create(:container => @version, :file => a, :author => logged_in_user) unless a.size == 0
365 } if params[:attachments] and params[:attachments].is_a? Array
365 } if params[:attachments] and params[:attachments].is_a? Array
366 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
366 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
367 end
367 end
368 @versions = @project.versions
368 @versions = @project.versions
369 end
369 end
370
370
371 def list_files
371 def list_files
372 @versions = @project.versions
372 @versions = @project.versions
373 end
373 end
374
374
375 # Show changelog for @project
375 # Show changelog for @project
376 def changelog
376 def changelog
377 @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
377 @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
378 if request.get?
378 if request.get?
379 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
379 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
380 else
380 else
381 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
381 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
382 end
382 end
383 @selected_tracker_ids ||= []
383 @selected_tracker_ids ||= []
384 @fixed_issues = @project.issues.find(:all,
384 @fixed_issues = @project.issues.find(:all,
385 :include => [ :fixed_version, :status, :tracker ],
385 :include => [ :fixed_version, :status, :tracker ],
386 :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
386 :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
387 :order => "versions.effective_date DESC, issues.id DESC"
387 :order => "versions.effective_date DESC, issues.id DESC"
388 ) unless @selected_tracker_ids.empty?
388 ) unless @selected_tracker_ids.empty?
389 @fixed_issues ||= []
389 @fixed_issues ||= []
390 end
390 end
391
391
392 def activity
392 def activity
393 if params[:year] and params[:year].to_i > 1900
393 if params[:year] and params[:year].to_i > 1900
394 @year = params[:year].to_i
394 @year = params[:year].to_i
395 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
395 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
396 @month = params[:month].to_i
396 @month = params[:month].to_i
397 end
397 end
398 end
398 end
399 @year ||= Date.today.year
399 @year ||= Date.today.year
400 @month ||= Date.today.month
400 @month ||= Date.today.month
401
401
402 @date_from = Date.civil(@year, @month, 1)
402 @date_from = Date.civil(@year, @month, 1)
403 @date_to = (@date_from >> 1)-1
403 @date_to = (@date_from >> 1)-1
404
404
405 @events_by_day = {}
405 @events_by_day = {}
406
406
407 unless params[:show_issues] == "0"
407 unless params[:show_issues] == "0"
408 @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
408 @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
409 @events_by_day[i.created_on.to_date] ||= []
409 @events_by_day[i.created_on.to_date] ||= []
410 @events_by_day[i.created_on.to_date] << i
410 @events_by_day[i.created_on.to_date] << i
411 }
411 }
412 @show_issues = 1
412 @show_issues = 1
413 end
413 end
414
414
415 unless params[:show_news] == "0"
415 unless params[:show_news] == "0"
416 @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to], :include => :author ).each { |i|
416 @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to], :include => :author ).each { |i|
417 @events_by_day[i.created_on.to_date] ||= []
417 @events_by_day[i.created_on.to_date] ||= []
418 @events_by_day[i.created_on.to_date] << i
418 @events_by_day[i.created_on.to_date] << i
419 }
419 }
420 @show_news = 1
420 @show_news = 1
421 end
421 end
422
422
423 unless params[:show_files] == "0"
423 unless params[:show_files] == "0"
424 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|
424 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|
425 @events_by_day[i.created_on.to_date] ||= []
425 @events_by_day[i.created_on.to_date] ||= []
426 @events_by_day[i.created_on.to_date] << i
426 @events_by_day[i.created_on.to_date] << i
427 }
427 }
428 @show_files = 1
428 @show_files = 1
429 end
429 end
430
430
431 unless params[:show_documents] == "0"
431 unless params[:show_documents] == "0"
432 @project.documents.find(:all, :conditions => ["documents.created_on>=? and documents.created_on<=?", @date_from, @date_to] ).each { |i|
432 @project.documents.find(:all, :conditions => ["documents.created_on>=? and documents.created_on<=?", @date_from, @date_to] ).each { |i|
433 @events_by_day[i.created_on.to_date] ||= []
433 @events_by_day[i.created_on.to_date] ||= []
434 @events_by_day[i.created_on.to_date] << i
434 @events_by_day[i.created_on.to_date] << i
435 }
435 }
436 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|
436 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|
437 @events_by_day[i.created_on.to_date] ||= []
437 @events_by_day[i.created_on.to_date] ||= []
438 @events_by_day[i.created_on.to_date] << i
438 @events_by_day[i.created_on.to_date] << i
439 }
439 }
440 @show_documents = 1
440 @show_documents = 1
441 end
441 end
442
442
443 render :layout => false if request.xhr?
443 render :layout => false if request.xhr?
444 end
444 end
445
445
446 def calendar
446 def calendar
447 if params[:year] and params[:year].to_i > 1900
447 if params[:year] and params[:year].to_i > 1900
448 @year = params[:year].to_i
448 @year = params[:year].to_i
449 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
449 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
450 @month = params[:month].to_i
450 @month = params[:month].to_i
451 end
451 end
452 end
452 end
453 @year ||= Date.today.year
453 @year ||= Date.today.year
454 @month ||= Date.today.month
454 @month ||= Date.today.month
455
455
456 @date_from = Date.civil(@year, @month, 1)
456 @date_from = Date.civil(@year, @month, 1)
457 @date_to = (@date_from >> 1)-1
457 @date_to = (@date_from >> 1)-1
458 # start on monday
458 # start on monday
459 @date_from = @date_from - (@date_from.cwday-1)
459 @date_from = @date_from - (@date_from.cwday-1)
460 # finish on sunday
460 # finish on sunday
461 @date_to = @date_to + (7-@date_to.cwday)
461 @date_to = @date_to + (7-@date_to.cwday)
462
462
463 @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])
463 @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])
464 render :layout => false if request.xhr?
464 render :layout => false if request.xhr?
465 end
465 end
466
466
467 def gantt
467 def gantt
468 if params[:year] and params[:year].to_i >0
468 if params[:year] and params[:year].to_i >0
469 @year_from = params[:year].to_i
469 @year_from = params[:year].to_i
470 if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
470 if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
471 @month_from = params[:month].to_i
471 @month_from = params[:month].to_i
472 else
472 else
473 @month_from = 1
473 @month_from = 1
474 end
474 end
475 else
475 else
476 @month_from ||= (Date.today << 1).month
476 @month_from ||= (Date.today << 1).month
477 @year_from ||= (Date.today << 1).year
477 @year_from ||= (Date.today << 1).year
478 end
478 end
479
479
480 @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
480 @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
481 @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
481 @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
482
482
483 @date_from = Date.civil(@year_from, @month_from, 1)
483 @date_from = Date.civil(@year_from, @month_from, 1)
484 @date_to = (@date_from >> @months) - 1
484 @date_to = (@date_from >> @months) - 1
485 @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])
485 @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])
486
486
487 if params[:output]=='pdf'
487 if params[:output]=='pdf'
488 @options_for_rfpdf ||= {}
488 @options_for_rfpdf ||= {}
489 @options_for_rfpdf[:file_name] = "gantt.pdf"
489 @options_for_rfpdf[:file_name] = "gantt.pdf"
490 render :template => "projects/gantt.rfpdf", :layout => false
490 render :template => "projects/gantt.rfpdf", :layout => false
491 else
491 else
492 render :template => "projects/gantt.rhtml"
492 render :template => "projects/gantt.rhtml"
493 end
493 end
494 end
494 end
495
495
496 private
496 private
497 # Find project of id params[:id]
497 # Find project of id params[:id]
498 # if not found, redirect to project list
498 # if not found, redirect to project list
499 # Used as a before_filter
499 # Used as a before_filter
500 def find_project
500 def find_project
501 @project = Project.find(params[:id])
501 @project = Project.find(params[:id])
502 @html_title = @project.name
502 @html_title = @project.name
503 rescue
503 rescue ActiveRecord::RecordNotFound
504 redirect_to :action => 'list'
504 render_404
505 end
505 end
506
506
507 # Retrieve query from session or build a new query
507 # Retrieve query from session or build a new query
508 def retrieve_query
508 def retrieve_query
509 if params[:query_id]
509 if params[:query_id]
510 @query = @project.queries.find(params[:query_id])
510 @query = @project.queries.find(params[:query_id])
511 else
511 else
512 if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
512 if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
513 # Give it a name, required to be valid
513 # Give it a name, required to be valid
514 @query = Query.new(:name => "_")
514 @query = Query.new(:name => "_")
515 @query.project = @project
515 @query.project = @project
516 if params[:fields] and params[:fields].is_a? Array
516 if params[:fields] and params[:fields].is_a? Array
517 params[:fields].each do |field|
517 params[:fields].each do |field|
518 @query.add_filter(field, params[:operators][field], params[:values][field])
518 @query.add_filter(field, params[:operators][field], params[:values][field])
519 end
519 end
520 else
520 else
521 @query.available_filters.keys.each do |field|
521 @query.available_filters.keys.each do |field|
522 @query.add_short_filter(field, params[field]) if params[field]
522 @query.add_short_filter(field, params[field]) if params[field]
523 end
523 end
524 end
524 end
525 session[:query] = @query
525 session[:query] = @query
526 else
526 else
527 @query = session[:query]
527 @query = session[:query]
528 end
528 end
529 end
529 end
530 end
530 end
531 end
531 end
@@ -1,49 +1,51
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 QueriesController < ApplicationController
18 class QueriesController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :require_login, :find_query
20 before_filter :require_login, :find_query
21
21
22 def edit
22 def edit
23 if request.post?
23 if request.post?
24 @query.filters = {}
24 @query.filters = {}
25 params[:fields].each do |field|
25 params[:fields].each do |field|
26 @query.add_filter(field, params[:operators][field], params[:values][field])
26 @query.add_filter(field, params[:operators][field], params[:values][field])
27 end if params[:fields]
27 end if params[:fields]
28 @query.attributes = params[:query]
28 @query.attributes = params[:query]
29
29
30 if @query.save
30 if @query.save
31 flash[:notice] = l(:notice_successful_update)
31 flash[:notice] = l(:notice_successful_update)
32 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
32 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
33 end
33 end
34 end
34 end
35 end
35 end
36
36
37 def destroy
37 def destroy
38 @query.destroy if request.post?
38 @query.destroy if request.post?
39 redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
39 redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
40 end
40 end
41
41
42 private
42 private
43 def find_query
43 def find_query
44 @query = Query.find(params[:id])
44 @query = Query.find(params[:id])
45 @project = @query.project
45 @project = @query.project
46 # check if user is allowed to manage queries (same permission as add_query)
46 # check if user is allowed to manage queries (same permission as add_query)
47 authorize('projects', 'add_query')
47 authorize('projects', 'add_query')
48 rescue ActiveRecord::RecordNotFound
49 render_404
48 end
50 end
49 end
51 end
@@ -1,165 +1,167
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 ReportsController < ApplicationController
18 class ReportsController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def issue_report
22 def issue_report
23 @statuses = IssueStatus.find :all
23 @statuses = IssueStatus.find :all
24
24
25 case params[:detail]
25 case params[:detail]
26 when "tracker"
26 when "tracker"
27 @field = "tracker_id"
27 @field = "tracker_id"
28 @rows = Tracker.find :all
28 @rows = Tracker.find :all
29 @data = issues_by_tracker
29 @data = issues_by_tracker
30 @report_title = l(:field_tracker)
30 @report_title = l(:field_tracker)
31 render :template => "reports/issue_report_details"
31 render :template => "reports/issue_report_details"
32 when "priority"
32 when "priority"
33 @field = "priority_id"
33 @field = "priority_id"
34 @rows = Enumeration::get_values('IPRI')
34 @rows = Enumeration::get_values('IPRI')
35 @data = issues_by_priority
35 @data = issues_by_priority
36 @report_title = l(:field_priority)
36 @report_title = l(:field_priority)
37 render :template => "reports/issue_report_details"
37 render :template => "reports/issue_report_details"
38 when "category"
38 when "category"
39 @field = "category_id"
39 @field = "category_id"
40 @rows = @project.issue_categories
40 @rows = @project.issue_categories
41 @data = issues_by_category
41 @data = issues_by_category
42 @report_title = l(:field_category)
42 @report_title = l(:field_category)
43 render :template => "reports/issue_report_details"
43 render :template => "reports/issue_report_details"
44 when "author"
44 when "author"
45 @field = "author_id"
45 @field = "author_id"
46 @rows = @project.members.collect { |m| m.user }
46 @rows = @project.members.collect { |m| m.user }
47 @data = issues_by_author
47 @data = issues_by_author
48 @report_title = l(:field_author)
48 @report_title = l(:field_author)
49 render :template => "reports/issue_report_details"
49 render :template => "reports/issue_report_details"
50 else
50 else
51 @queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)]
51 @queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)]
52 @trackers = Tracker.find(:all)
52 @trackers = Tracker.find(:all)
53 @priorities = Enumeration::get_values('IPRI')
53 @priorities = Enumeration::get_values('IPRI')
54 @categories = @project.issue_categories
54 @categories = @project.issue_categories
55 @authors = @project.members.collect { |m| m.user }
55 @authors = @project.members.collect { |m| m.user }
56 issues_by_tracker
56 issues_by_tracker
57 issues_by_priority
57 issues_by_priority
58 issues_by_category
58 issues_by_category
59 issues_by_author
59 issues_by_author
60 render :template => "reports/issue_report"
60 render :template => "reports/issue_report"
61 end
61 end
62 end
62 end
63
63
64 def delays
64 def delays
65 @trackers = Tracker.find(:all)
65 @trackers = Tracker.find(:all)
66 if request.get?
66 if request.get?
67 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
67 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
68 else
68 else
69 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
69 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
70 end
70 end
71 @selected_tracker_ids ||= []
71 @selected_tracker_ids ||= []
72 @raw =
72 @raw =
73 ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total
73 ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total
74 FROM issue_histories a, issue_histories b, issues i
74 FROM issue_histories a, issue_histories b, issues i
75 WHERE a.status_id =5
75 WHERE a.status_id =5
76 AND a.issue_id = b.issue_id
76 AND a.issue_id = b.issue_id
77 AND a.issue_id = i.id
77 AND a.issue_id = i.id
78 AND i.tracker_id in (#{@selected_tracker_ids.join(',')})
78 AND i.tracker_id in (#{@selected_tracker_ids.join(',')})
79 AND b.id = (
79 AND b.id = (
80 SELECT min( c.id )
80 SELECT min( c.id )
81 FROM issue_histories c
81 FROM issue_histories c
82 WHERE b.issue_id = c.issue_id )
82 WHERE b.issue_id = c.issue_id )
83 GROUP BY delay") unless @selected_tracker_ids.empty?
83 GROUP BY delay") unless @selected_tracker_ids.empty?
84 @raw ||=[]
84 @raw ||=[]
85
85
86 @x_from = 0
86 @x_from = 0
87 @x_to = 0
87 @x_to = 0
88 @y_from = 0
88 @y_from = 0
89 @y_to = 0
89 @y_to = 0
90 @sum_total = 0
90 @sum_total = 0
91 @sum_delay = 0
91 @sum_delay = 0
92 @raw.each do |r|
92 @raw.each do |r|
93 @x_to = [r['delay'].to_i, @x_to].max
93 @x_to = [r['delay'].to_i, @x_to].max
94 @y_to = [r['total'].to_i, @y_to].max
94 @y_to = [r['total'].to_i, @y_to].max
95 @sum_total = @sum_total + r['total'].to_i
95 @sum_total = @sum_total + r['total'].to_i
96 @sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i
96 @sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i
97 end
97 end
98 end
98 end
99
99
100 private
100 private
101 # Find project of id params[:id]
101 # Find project of id params[:id]
102 def find_project
102 def find_project
103 @project = Project.find(params[:id])
103 @project = Project.find(params[:id])
104 end
104 rescue ActiveRecord::RecordNotFound
105 render_404
106 end
105
107
106 def issues_by_tracker
108 def issues_by_tracker
107 @issues_by_tracker ||=
109 @issues_by_tracker ||=
108 ActiveRecord::Base.connection.select_all("select s.id as status_id,
110 ActiveRecord::Base.connection.select_all("select s.id as status_id,
109 s.is_closed as closed,
111 s.is_closed as closed,
110 t.id as tracker_id,
112 t.id as tracker_id,
111 count(i.id) as total
113 count(i.id) as total
112 from
114 from
113 issues i, issue_statuses s, trackers t
115 issues i, issue_statuses s, trackers t
114 where
116 where
115 i.status_id=s.id
117 i.status_id=s.id
116 and i.tracker_id=t.id
118 and i.tracker_id=t.id
117 and i.project_id=#{@project.id}
119 and i.project_id=#{@project.id}
118 group by s.id, s.is_closed, t.id")
120 group by s.id, s.is_closed, t.id")
119 end
121 end
120
122
121 def issues_by_priority
123 def issues_by_priority
122 @issues_by_priority ||=
124 @issues_by_priority ||=
123 ActiveRecord::Base.connection.select_all("select s.id as status_id,
125 ActiveRecord::Base.connection.select_all("select s.id as status_id,
124 s.is_closed as closed,
126 s.is_closed as closed,
125 p.id as priority_id,
127 p.id as priority_id,
126 count(i.id) as total
128 count(i.id) as total
127 from
129 from
128 issues i, issue_statuses s, enumerations p
130 issues i, issue_statuses s, enumerations p
129 where
131 where
130 i.status_id=s.id
132 i.status_id=s.id
131 and i.priority_id=p.id
133 and i.priority_id=p.id
132 and i.project_id=#{@project.id}
134 and i.project_id=#{@project.id}
133 group by s.id, s.is_closed, p.id")
135 group by s.id, s.is_closed, p.id")
134 end
136 end
135
137
136 def issues_by_category
138 def issues_by_category
137 @issues_by_category ||=
139 @issues_by_category ||=
138 ActiveRecord::Base.connection.select_all("select s.id as status_id,
140 ActiveRecord::Base.connection.select_all("select s.id as status_id,
139 s.is_closed as closed,
141 s.is_closed as closed,
140 c.id as category_id,
142 c.id as category_id,
141 count(i.id) as total
143 count(i.id) as total
142 from
144 from
143 issues i, issue_statuses s, issue_categories c
145 issues i, issue_statuses s, issue_categories c
144 where
146 where
145 i.status_id=s.id
147 i.status_id=s.id
146 and i.category_id=c.id
148 and i.category_id=c.id
147 and i.project_id=#{@project.id}
149 and i.project_id=#{@project.id}
148 group by s.id, s.is_closed, c.id")
150 group by s.id, s.is_closed, c.id")
149 end
151 end
150
152
151 def issues_by_author
153 def issues_by_author
152 @issues_by_author ||=
154 @issues_by_author ||=
153 ActiveRecord::Base.connection.select_all("select s.id as status_id,
155 ActiveRecord::Base.connection.select_all("select s.id as status_id,
154 s.is_closed as closed,
156 s.is_closed as closed,
155 a.id as author_id,
157 a.id as author_id,
156 count(i.id) as total
158 count(i.id) as total
157 from
159 from
158 issues i, issue_statuses s, users a
160 issues i, issue_statuses s, users a
159 where
161 where
160 i.status_id=s.id
162 i.status_id=s.id
161 and i.author_id=a.id
163 and i.author_id=a.id
162 and i.project_id=#{@project.id}
164 and i.project_id=#{@project.id}
163 group by s.id, s.is_closed, a.id")
165 group by s.id, s.is_closed, a.id")
164 end
166 end
165 end
167 end
@@ -1,72 +1,74
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 RepositoriesController < ApplicationController
18 class RepositoriesController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def show
22 def show
23 @entries = @repository.scm.entries('')
23 @entries = @repository.scm.entries('')
24 show_error and return unless @entries
24 show_error and return unless @entries
25 @latest_revision = @entries.revisions.latest
25 @latest_revision = @entries.revisions.latest
26 end
26 end
27
27
28 def browse
28 def browse
29 @entries = @repository.scm.entries(@path, @rev)
29 @entries = @repository.scm.entries(@path, @rev)
30 show_error and return unless @entries
30 show_error and return unless @entries
31 end
31 end
32
32
33 def revisions
33 def revisions
34 @entry = @repository.scm.entry(@path, @rev)
34 @entry = @repository.scm.entry(@path, @rev)
35 @revisions = @repository.scm.revisions(@path, @rev)
35 @revisions = @repository.scm.revisions(@path, @rev)
36 show_error and return unless @entry && @revisions
36 show_error and return unless @entry && @revisions
37 end
37 end
38
38
39 def entry
39 def entry
40 if 'raw' == params[:format]
40 if 'raw' == params[:format]
41 content = @repository.scm.cat(@path, @rev)
41 content = @repository.scm.cat(@path, @rev)
42 show_error and return unless content
42 show_error and return unless content
43 send_data content, :filename => @path.split('/').last
43 send_data content, :filename => @path.split('/').last
44 end
44 end
45 end
45 end
46
46
47 def revision
47 def revision
48 @revisions = @repository.scm.revisions '', @rev, @rev, :with_paths => true
48 @revisions = @repository.scm.revisions '', @rev, @rev, :with_paths => true
49 show_error and return unless @revisions
49 show_error and return unless @revisions
50 @revision = @revisions.first
50 @revision = @revisions.first
51 end
51 end
52
52
53 def diff
53 def diff
54 @rev_to = params[:rev_to] || (@rev-1)
54 @rev_to = params[:rev_to] || (@rev-1)
55 @diff = @repository.scm.diff(params[:path], @rev, @rev_to)
55 @diff = @repository.scm.diff(params[:path], @rev, @rev_to)
56 show_error and return unless @diff
56 show_error and return unless @diff
57 end
57 end
58
58
59 private
59 private
60 def find_project
60 def find_project
61 @project = Project.find(params[:id])
61 @project = Project.find(params[:id])
62 @repository = @project.repository
62 @repository = @project.repository
63 @path = params[:path].squeeze('/').gsub(/^\//, '') if params[:path]
63 @path = params[:path].squeeze('/').gsub(/^\//, '') if params[:path]
64 @path ||= ''
64 @path ||= ''
65 @rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
65 @rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
66 rescue ActiveRecord::RecordNotFound
67 render_404
66 end
68 end
67
69
68 def show_error
70 def show_error
69 flash.now[:notice] = l(:notice_scm_error)
71 flash.now[:notice] = l(:notice_scm_error)
70 render :nothing => true, :layout => true
72 render :nothing => true, :layout => true
71 end
73 end
72 end
74 end
@@ -1,57 +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 VersionsController < ApplicationController
18 class VersionsController < ApplicationController
19 layout 'base'
19 layout 'base'
20 before_filter :find_project, :authorize
20 before_filter :find_project, :authorize
21
21
22 def edit
22 def edit
23 if request.post? and @version.update_attributes(params[:version])
23 if request.post? and @version.update_attributes(params[:version])
24 flash[:notice] = l(:notice_successful_update)
24 flash[:notice] = l(:notice_successful_update)
25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
26 end
26 end
27 end
27 end
28
28
29 def destroy
29 def destroy
30 @version.destroy
30 @version.destroy
31 redirect_to :controller => 'projects', :action => 'settings', :id => @project
31 redirect_to :controller => 'projects', :action => 'settings', :id => @project
32 rescue
32 rescue
33 flash[:notice] = "Unable to delete version"
33 flash[:notice] = "Unable to delete version"
34 redirect_to :controller => 'projects', :action => 'settings', :id => @project
34 redirect_to :controller => 'projects', :action => 'settings', :id => @project
35 end
35 end
36
36
37 def download
37 def download
38 @attachment = @version.attachments.find(params[:attachment_id])
38 @attachment = @version.attachments.find(params[:attachment_id])
39 @attachment.increment_download
39 @attachment.increment_download
40 send_file @attachment.diskfile, :filename => @attachment.filename
40 send_file @attachment.diskfile, :filename => @attachment.filename
41 rescue
41 rescue
42 flash.now[:notice] = l(:notice_file_not_found)
42 render_404
43 render :text => "", :layout => true, :status => 404
44 end
43 end
45
44
46 def destroy_file
45 def destroy_file
47 @version.attachments.find(params[:attachment_id]).destroy
46 @version.attachments.find(params[:attachment_id]).destroy
48 flash[:notice] = l(:notice_successful_delete)
47 flash[:notice] = l(:notice_successful_delete)
49 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
48 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
50 end
49 end
51
50
52 private
51 private
53 def find_project
52 def find_project
54 @version = Version.find(params[:id])
53 @version = Version.find(params[:id])
55 @project = @version.project
54 @project = @version.project
55 rescue ActiveRecord::RecordNotFound
56 render_404
56 end
57 end
57 end
58 end
General Comments 0
You need to be logged in to leave comments. Login now