##// END OF EJS Templates
Issue history is now 'oldest first' sorted....
Jean-Philippe Lang -
r627:ecf208f6604a
parent child
Show More
@@ -1,163 +1,163
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class 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 cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
22 cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
23
23
24 helper :projects
24 helper :projects
25 include ProjectsHelper
25 include ProjectsHelper
26 helper :custom_fields
26 helper :custom_fields
27 include CustomFieldsHelper
27 include CustomFieldsHelper
28 helper :ifpdf
28 helper :ifpdf
29 include IfpdfHelper
29 include IfpdfHelper
30 helper :issue_relations
30 helper :issue_relations
31 include IssueRelationsHelper
31 include IssueRelationsHelper
32 helper :watchers
32 helper :watchers
33 include WatchersHelper
33 include WatchersHelper
34 helper :attachments
34 helper :attachments
35 include AttachmentsHelper
35 include AttachmentsHelper
36
36
37 def show
37 def show
38 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
38 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
39 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
39 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
40 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on desc")
40 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
41 end
41 end
42
42
43 def export_pdf
43 def export_pdf
44 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
44 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
45 @options_for_rfpdf ||= {}
45 @options_for_rfpdf ||= {}
46 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.id}.pdf"
46 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.id}.pdf"
47 end
47 end
48
48
49 def edit
49 def edit
50 @priorities = Enumeration::get_values('IPRI')
50 @priorities = Enumeration::get_values('IPRI')
51 if request.get?
51 if request.get?
52 @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) }
52 @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) }
53 else
53 else
54 begin
54 begin
55 @issue.init_journal(self.logged_in_user)
55 @issue.init_journal(self.logged_in_user)
56 # Retrieve custom fields and values
56 # Retrieve custom fields and values
57 @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]) }
57 @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]) }
58 @issue.custom_values = @custom_values
58 @issue.custom_values = @custom_values
59 @issue.attributes = params[:issue]
59 @issue.attributes = params[:issue]
60 if @issue.save
60 if @issue.save
61 flash[:notice] = l(:notice_successful_update)
61 flash[:notice] = l(:notice_successful_update)
62 redirect_to :action => 'show', :id => @issue
62 redirect_to :action => 'show', :id => @issue
63 end
63 end
64 rescue ActiveRecord::StaleObjectError
64 rescue ActiveRecord::StaleObjectError
65 # Optimistic locking exception
65 # Optimistic locking exception
66 flash[:error] = l(:notice_locking_conflict)
66 flash[:error] = l(:notice_locking_conflict)
67 end
67 end
68 end
68 end
69 end
69 end
70
70
71 def add_note
71 def add_note
72 unless params[:notes].empty?
72 unless params[:notes].empty?
73 journal = @issue.init_journal(self.logged_in_user, params[:notes])
73 journal = @issue.init_journal(self.logged_in_user, params[:notes])
74 if @issue.save
74 if @issue.save
75 flash[:notice] = l(:notice_successful_update)
75 flash[:notice] = l(:notice_successful_update)
76 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
76 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
77 redirect_to :action => 'show', :id => @issue
77 redirect_to :action => 'show', :id => @issue
78 return
78 return
79 end
79 end
80 end
80 end
81 show
81 show
82 render :action => 'show'
82 render :action => 'show'
83 end
83 end
84
84
85 def change_status
85 def change_status
86 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
86 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if 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 journal = @issue.init_journal(self.logged_in_user, params[:notes])
90 journal = @issue.init_journal(self.logged_in_user, params[:notes])
91 @issue.status = @new_status
91 @issue.status = @new_status
92 if @issue.update_attributes(params[:issue])
92 if @issue.update_attributes(params[:issue])
93 # Save attachments
93 # Save attachments
94 params[:attachments].each { |file|
94 params[:attachments].each { |file|
95 next unless file.size > 0
95 next unless file.size > 0
96 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
96 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
97 journal.details << JournalDetail.new(:property => 'attachment',
97 journal.details << JournalDetail.new(:property => 'attachment',
98 :prop_key => a.id,
98 :prop_key => a.id,
99 :value => a.filename) unless a.new_record?
99 :value => a.filename) unless a.new_record?
100 } if params[:attachments] and params[:attachments].is_a? Array
100 } if params[:attachments] and params[:attachments].is_a? Array
101
101
102 # Log time
102 # Log time
103 if logged_in_user.authorized_to(@project, "timelog/edit")
103 if logged_in_user.authorized_to(@project, "timelog/edit")
104 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
104 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
105 @time_entry.attributes = params[:time_entry]
105 @time_entry.attributes = params[:time_entry]
106 @time_entry.save
106 @time_entry.save
107 end
107 end
108
108
109 flash[:notice] = l(:notice_successful_update)
109 flash[:notice] = l(:notice_successful_update)
110 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
110 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
111 redirect_to :action => 'show', :id => @issue
111 redirect_to :action => 'show', :id => @issue
112 end
112 end
113 rescue ActiveRecord::StaleObjectError
113 rescue ActiveRecord::StaleObjectError
114 # Optimistic locking exception
114 # Optimistic locking exception
115 flash[:error] = l(:notice_locking_conflict)
115 flash[:error] = l(:notice_locking_conflict)
116 end
116 end
117 end
117 end
118 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
118 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
119 @activities = Enumeration::get_values('ACTI')
119 @activities = Enumeration::get_values('ACTI')
120 end
120 end
121
121
122 def destroy
122 def destroy
123 @issue.destroy
123 @issue.destroy
124 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
124 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
125 end
125 end
126
126
127 def add_attachment
127 def add_attachment
128 # Save the attachments
128 # Save the attachments
129 @attachments = []
129 @attachments = []
130 journal = @issue.init_journal(self.logged_in_user)
130 journal = @issue.init_journal(self.logged_in_user)
131 params[:attachments].each { |file|
131 params[:attachments].each { |file|
132 next unless file.size > 0
132 next unless file.size > 0
133 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
133 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
134 @attachments << a unless a.new_record?
134 @attachments << a unless a.new_record?
135 journal.details << JournalDetail.new(:property => 'attachment',
135 journal.details << JournalDetail.new(:property => 'attachment',
136 :prop_key => a.id,
136 :prop_key => a.id,
137 :value => a.filename) unless a.new_record?
137 :value => a.filename) unless a.new_record?
138 } if params[:attachments] and params[:attachments].is_a? Array
138 } if params[:attachments] and params[:attachments].is_a? Array
139 journal.save if journal.details.any?
139 journal.save if journal.details.any?
140 Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
140 Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
141 redirect_to :action => 'show', :id => @issue
141 redirect_to :action => 'show', :id => @issue
142 end
142 end
143
143
144 def destroy_attachment
144 def destroy_attachment
145 a = @issue.attachments.find(params[:attachment_id])
145 a = @issue.attachments.find(params[:attachment_id])
146 a.destroy
146 a.destroy
147 journal = @issue.init_journal(self.logged_in_user)
147 journal = @issue.init_journal(self.logged_in_user)
148 journal.details << JournalDetail.new(:property => 'attachment',
148 journal.details << JournalDetail.new(:property => 'attachment',
149 :prop_key => a.id,
149 :prop_key => a.id,
150 :old_value => a.filename)
150 :old_value => a.filename)
151 journal.save
151 journal.save
152 redirect_to :action => 'show', :id => @issue
152 redirect_to :action => 'show', :id => @issue
153 end
153 end
154
154
155 private
155 private
156 def find_project
156 def find_project
157 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
157 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
158 @project = @issue.project
158 @project = @issue.project
159 @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
159 @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
160 rescue ActiveRecord::RecordNotFound
160 rescue ActiveRecord::RecordNotFound
161 render_404
161 render_404
162 end
162 end
163 end
163 end
@@ -1,13 +1,13
1 <% note_id = journals.length %>
1 <% note_id = 1 %>
2 <% for journal in journals %>
2 <% for journal in journals %>
3 <h4><div style="float:right;"><%= link_to "##{note_id}", :anchor => "note-#{note_id}" %></div>
3 <h4><div style="float:right;"><%= link_to "##{note_id}", :anchor => "note-#{note_id}" %></div>
4 <%= content_tag('a', '', :name => "note-#{note_id}")%>
4 <%= content_tag('a', '', :name => "note-#{note_id}")%>
5 <%= format_time(journal.created_on) %> - <%= journal.user.name %></h4>
5 <%= format_time(journal.created_on) %> - <%= journal.user.name %></h4>
6 <ul>
6 <ul>
7 <% for detail in journal.details %>
7 <% for detail in journal.details %>
8 <li><%= show_detail(detail) %></li>
8 <li><%= show_detail(detail) %></li>
9 <% end %>
9 <% end %>
10 </ul>
10 </ul>
11 <%= textilizable(journal.notes) unless journal.notes.blank? %>
11 <%= textilizable(journal.notes) unless journal.notes.blank? %>
12 <% note_id -= 1 %>
12 <% note_id += 1 %>
13 <% end %>
13 <% end %>
General Comments 0
You need to be logged in to leave comments. Login now