##// END OF EJS Templates
Issue#long_id no more used and removed...
Jean-Philippe Lang -
r507:71e6f22670fe
parent child
Show More
@@ -1,161 +1,161
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class IssuesController < ApplicationController
19 19 layout 'base', :except => :export_pdf
20 20 before_filter :find_project, :authorize
21 21
22 22 helper :custom_fields
23 23 include CustomFieldsHelper
24 24 helper :ifpdf
25 25 include IfpdfHelper
26 26 helper :issue_relations
27 27 include IssueRelationsHelper
28 28
29 29 def show
30 30 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
31 31 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
32 32 @journals_count = @issue.journals.count
33 33 @journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "#{Journal.table_name}.created_on desc")
34 34 end
35 35
36 36 def history
37 37 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on desc")
38 38 @journals_count = @journals.length
39 39 end
40 40
41 41 def export_pdf
42 42 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
43 43 @options_for_rfpdf ||= {}
44 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
44 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.id}.pdf"
45 45 end
46 46
47 47 def edit
48 48 @priorities = Enumeration::get_values('IPRI')
49 49 if request.get?
50 50 @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) }
51 51 else
52 52 begin
53 53 @issue.init_journal(self.logged_in_user)
54 54 # Retrieve custom fields and values
55 55 @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]) }
56 56 @issue.custom_values = @custom_values
57 57 @issue.attributes = params[:issue]
58 58 if @issue.save
59 59 flash[:notice] = l(:notice_successful_update)
60 60 redirect_to :action => 'show', :id => @issue
61 61 end
62 62 rescue ActiveRecord::StaleObjectError
63 63 # Optimistic locking exception
64 64 flash[:notice] = l(:notice_locking_conflict)
65 65 end
66 66 end
67 67 end
68 68
69 69 def add_note
70 70 unless params[:notes].empty?
71 71 journal = @issue.init_journal(self.logged_in_user, params[:notes])
72 72 if @issue.save
73 73 flash[:notice] = l(:notice_successful_update)
74 74 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
75 75 redirect_to :action => 'show', :id => @issue
76 76 return
77 77 end
78 78 end
79 79 show
80 80 render :action => 'show'
81 81 end
82 82
83 83 def change_status
84 84 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
85 85 @new_status = IssueStatus.find(params[:new_status_id])
86 86 if params[:confirm]
87 87 begin
88 88 journal = @issue.init_journal(self.logged_in_user, params[:notes])
89 89 @issue.status = @new_status
90 90 if @issue.update_attributes(params[:issue])
91 91 # Save attachments
92 92 params[:attachments].each { |file|
93 93 next unless file.size > 0
94 94 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
95 95 journal.details << JournalDetail.new(:property => 'attachment',
96 96 :prop_key => a.id,
97 97 :value => a.filename) unless a.new_record?
98 98 } if params[:attachments] and params[:attachments].is_a? Array
99 99
100 100 flash[:notice] = l(:notice_successful_update)
101 101 Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
102 102 redirect_to :action => 'show', :id => @issue
103 103 end
104 104 rescue ActiveRecord::StaleObjectError
105 105 # Optimistic locking exception
106 106 flash[:notice] = l(:notice_locking_conflict)
107 107 end
108 108 end
109 109 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
110 110 end
111 111
112 112 def destroy
113 113 @issue.destroy
114 114 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
115 115 end
116 116
117 117 def add_attachment
118 118 # Save the attachments
119 119 @attachments = []
120 120 journal = @issue.init_journal(self.logged_in_user)
121 121 params[:attachments].each { |file|
122 122 next unless file.size > 0
123 123 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
124 124 @attachments << a unless a.new_record?
125 125 journal.details << JournalDetail.new(:property => 'attachment',
126 126 :prop_key => a.id,
127 127 :value => a.filename) unless a.new_record?
128 128 } if params[:attachments] and params[:attachments].is_a? Array
129 129 journal.save if journal.details.any?
130 130 Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
131 131 redirect_to :action => 'show', :id => @issue
132 132 end
133 133
134 134 def destroy_attachment
135 135 a = @issue.attachments.find(params[:attachment_id])
136 136 a.destroy
137 137 journal = @issue.init_journal(self.logged_in_user)
138 138 journal.details << JournalDetail.new(:property => 'attachment',
139 139 :prop_key => a.id,
140 140 :old_value => a.filename)
141 141 journal.save
142 142 redirect_to :action => 'show', :id => @issue
143 143 end
144 144
145 145 # Send the file in stream mode
146 146 def download
147 147 @attachment = @issue.attachments.find(params[:attachment_id])
148 148 send_file @attachment.diskfile, :filename => @attachment.filename
149 149 rescue
150 150 render_404
151 151 end
152 152
153 153 private
154 154 def find_project
155 155 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
156 156 @project = @issue.project
157 157 @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
158 158 rescue ActiveRecord::RecordNotFound
159 159 render_404
160 160 end
161 161 end
@@ -1,128 +1,124
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Issue < ActiveRecord::Base
19 19 belongs_to :project
20 20 belongs_to :tracker
21 21 belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
22 22 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
23 23 belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
24 24 belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
25 25 belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
26 26 belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
27 27
28 28 has_many :journals, :as => :journalized, :dependent => :destroy
29 29 has_many :attachments, :as => :container, :dependent => :destroy
30 30 has_many :time_entries
31 31 has_many :custom_values, :dependent => :delete_all, :as => :customized
32 32 has_many :custom_fields, :through => :custom_values
33 33 has_and_belongs_to_many :changesets, :order => "revision ASC"
34 34
35 35 has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
36 36 has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
37 37
38 38 acts_as_watchable
39 39
40 40 validates_presence_of :subject, :description, :priority, :tracker, :author, :status
41 41 validates_inclusion_of :done_ratio, :in => 0..100
42 42 validates_associated :custom_values, :on => :update
43 43
44 44 # set default status for new issues
45 45 def before_validation
46 46 self.status = IssueStatus.default if status.nil?
47 47 end
48 48
49 49 def validate
50 50 if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
51 51 errors.add :due_date, :activerecord_error_not_a_date
52 52 end
53 53
54 54 if self.due_date and self.start_date and self.due_date < self.start_date
55 55 errors.add :due_date, :activerecord_error_greater_than_start_date
56 56 end
57 57
58 58 if start_date && soonest_start && start_date < soonest_start
59 59 errors.add :start_date, :activerecord_error_invalid
60 60 end
61 61 end
62 62
63 63 def before_save
64 64 if @current_journal
65 65 # attributes changes
66 66 (Issue.column_names - %w(id description)).each {|c|
67 67 @current_journal.details << JournalDetail.new(:property => 'attr',
68 68 :prop_key => c,
69 69 :old_value => @issue_before_change.send(c),
70 70 :value => send(c)) unless send(c)==@issue_before_change.send(c)
71 71 }
72 72 # custom fields changes
73 73 custom_values.each {|c|
74 74 @current_journal.details << JournalDetail.new(:property => 'cf',
75 75 :prop_key => c.custom_field_id,
76 76 :old_value => @custom_values_before_change[c.custom_field_id],
77 77 :value => c.value) unless @custom_values_before_change[c.custom_field_id]==c.value
78 78 }
79 79 @current_journal.save unless @current_journal.details.empty? and @current_journal.notes.empty?
80 80 end
81 81 end
82 82
83 83 def after_save
84 84 relations_from.each(&:set_issue_to_dates)
85 85 end
86 86
87 def long_id
88 "%05d" % self.id
89 end
90
91 87 def custom_value_for(custom_field)
92 88 self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
93 89 return nil
94 90 end
95 91
96 92 def init_journal(user, notes = "")
97 93 @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
98 94 @issue_before_change = self.clone
99 95 @custom_values_before_change = {}
100 96 self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
101 97 @current_journal
102 98 end
103 99
104 100 def spent_hours
105 101 @spent_hours ||= time_entries.sum(:hours) || 0
106 102 end
107 103
108 104 def relations
109 105 (relations_from + relations_to).sort
110 106 end
111 107
112 108 def all_dependent_issues
113 109 dependencies = []
114 110 relations_from.each do |relation|
115 111 dependencies << relation.issue_to
116 112 dependencies += relation.issue_to.all_dependent_issues
117 113 end
118 114 dependencies
119 115 end
120 116
121 117 def duration
122 118 (start_date && due_date) ? due_date - start_date : 0
123 119 end
124 120
125 121 def soonest_start
126 122 @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
127 123 end
128 124 end
@@ -1,100 +1,100
1 1 <% pdf.SetFontStyle('B',11)
2 pdf.Cell(190,10, "#{issue.project.name} - #{issue.tracker.name} # #{issue.long_id} - #{issue.subject}")
2 pdf.Cell(190,10, "#{issue.project.name} - #{issue.tracker.name} # #{issue.id}: #{issue.subject}")
3 3 pdf.Ln
4 4
5 5 y0 = pdf.GetY
6 6
7 7 pdf.SetFontStyle('B',9)
8 8 pdf.Cell(35,5, l(:field_status) + ":","LT")
9 9 pdf.SetFontStyle('',9)
10 10 pdf.Cell(60,5, issue.status.name,"RT")
11 11 pdf.SetFontStyle('B',9)
12 12 pdf.Cell(35,5, l(:field_priority) + ":","LT")
13 13 pdf.SetFontStyle('',9)
14 14 pdf.Cell(60,5, issue.priority.name,"RT")
15 15 pdf.Ln
16 16
17 17 pdf.SetFontStyle('B',9)
18 18 pdf.Cell(35,5, l(:field_author) + ":","L")
19 19 pdf.SetFontStyle('',9)
20 20 pdf.Cell(60,5, issue.author.name,"R")
21 21 pdf.SetFontStyle('B',9)
22 22 pdf.Cell(35,5, l(:field_category) + ":","L")
23 23 pdf.SetFontStyle('',9)
24 24 pdf.Cell(60,5, (issue.category ? issue.category.name : "-"),"R")
25 25 pdf.Ln
26 26
27 27 pdf.SetFontStyle('B',9)
28 28 pdf.Cell(35,5, l(:field_created_on) + ":","L")
29 29 pdf.SetFontStyle('',9)
30 30 pdf.Cell(60,5, format_date(issue.created_on),"R")
31 31 pdf.SetFontStyle('B',9)
32 32 pdf.Cell(35,5, l(:field_assigned_to) + ":","L")
33 33 pdf.SetFontStyle('',9)
34 34 pdf.Cell(60,5, (issue.assigned_to ? issue.assigned_to.name : "-"),"R")
35 35 pdf.Ln
36 36
37 37 pdf.SetFontStyle('B',9)
38 38 pdf.Cell(35,5, l(:field_updated_on) + ":","LB")
39 39 pdf.SetFontStyle('',9)
40 40 pdf.Cell(60,5, format_date(issue.updated_on),"RB")
41 41 pdf.SetFontStyle('B',9)
42 42 pdf.Cell(35,5, l(:field_due_date) + ":","LB")
43 43 pdf.SetFontStyle('',9)
44 44 pdf.Cell(60,5, format_date(issue.due_date),"RB")
45 45 pdf.Ln
46 46
47 47 for custom_value in issue.custom_values
48 48 pdf.SetFontStyle('B',9)
49 49 pdf.Cell(35,5, custom_value.custom_field.name + ":","L")
50 50 pdf.SetFontStyle('',9)
51 51 pdf.MultiCell(155,5, (show_value custom_value),"R")
52 52 end
53 53
54 54 pdf.SetFontStyle('B',9)
55 55 pdf.Cell(35,5, l(:field_subject) + ":","LTB")
56 56 pdf.SetFontStyle('',9)
57 57 pdf.Cell(155,5, issue.subject,"RTB")
58 58 pdf.Ln
59 59
60 60 pdf.SetFontStyle('B',9)
61 61 pdf.Cell(35,5, l(:field_description) + ":")
62 62 pdf.SetFontStyle('',9)
63 63 pdf.MultiCell(155,5, issue.description,"BR")
64 64
65 65 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
66 66 pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
67 67
68 68 pdf.Ln
69 69
70 70 pdf.SetFontStyle('B',9)
71 71 pdf.Cell(190,5, l(:label_history), "B")
72 72 pdf.Ln
73 73 for journal in issue.journals.find(:all, :include => :user, :order => "journals.created_on desc")
74 74 pdf.SetFontStyle('B',8)
75 75 pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
76 76 pdf.Ln
77 77 pdf.SetFontStyle('I',8)
78 78 for detail in journal.details
79 79 pdf.Cell(190,5, "- " + show_detail(detail, true))
80 80 pdf.Ln
81 81 end
82 82 if journal.notes?
83 83 pdf.SetFontStyle('',8)
84 84 pdf.MultiCell(190,5, journal.notes)
85 85 end
86 86 pdf.Ln
87 87 end
88 88
89 89 pdf.SetFontStyle('B',9)
90 90 pdf.Cell(190,5, l(:label_attachment_plural), "B")
91 91 pdf.Ln
92 92 for attachment in issue.attachments
93 93 pdf.SetFontStyle('',8)
94 94 pdf.Cell(80,5, attachment.filename)
95 95 pdf.Cell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
96 96 pdf.Cell(25,5, format_date(attachment.created_on),0,0,"R")
97 97 pdf.Cell(65,5, attachment.author.name,0,0,"R")
98 98 pdf.Ln
99 99 end
100 100 %> No newline at end of file
@@ -1,24 +1,24
1 1 <h2><%=l(:button_move)%></h2>
2 2
3 3
4 4 <% form_tag({:action => 'move_issues', :id => @project}, :class => "tabular") do %>
5 5
6 6 <div class="box">
7 7 <p><label><%= l(:label_issue_plural) %>:</label>
8 8 <% for issue in @issues %>
9 <b><%= link_to issue.long_id, :controller => 'issues', :action => 'show', :id => issue %></b> - <%=h issue.subject %>
9 <%= link_to_issue issue %>: <%=h issue.subject %>
10 10 <%= hidden_field_tag "issue_ids[]", issue.id %><br />
11 11 <% end %>
12 12 <i>(<%= @issues.length%> <%= lwr(:label_issue, @issues.length)%>)</i></p>
13 13
14 14 &nbsp;
15 15
16 16 <!--[form:issue]-->
17 17 <p><label for="new_project_id"><%=l(:field_project)%></label>
18 18 <%= select_tag "new_project_id", options_from_collection_for_select(@projects, "id", "name", @project.id) %></p>
19 19
20 20 <p><label for="new_tracker_id"><%=l(:field_tracker)%></label>
21 21 <%= select_tag "new_tracker_id", options_from_collection_for_select(@trackers, "id", "name") %></p>
22 22 </div>
23 23 <%= submit_tag l(:button_move) %>
24 24 <% end %>
General Comments 0
You need to be logged in to leave comments. Login now