##// END OF EJS Templates
Adds parent issue id to the issues CSV export....
Jean-Philippe Lang -
r3503:06d2c3fd4e4a
parent child
Show More
@@ -1,226 +1,228
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 module IssuesHelper
18 module IssuesHelper
19 include ApplicationHelper
19 include ApplicationHelper
20
20
21 def render_issue_tooltip(issue)
21 def render_issue_tooltip(issue)
22 @cached_label_start_date ||= l(:field_start_date)
22 @cached_label_start_date ||= l(:field_start_date)
23 @cached_label_due_date ||= l(:field_due_date)
23 @cached_label_due_date ||= l(:field_due_date)
24 @cached_label_assigned_to ||= l(:field_assigned_to)
24 @cached_label_assigned_to ||= l(:field_assigned_to)
25 @cached_label_priority ||= l(:field_priority)
25 @cached_label_priority ||= l(:field_priority)
26
26
27 link_to_issue(issue) + "<br /><br />" +
27 link_to_issue(issue) + "<br /><br />" +
28 "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />" +
28 "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />" +
29 "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />" +
29 "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />" +
30 "<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" +
30 "<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" +
31 "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
31 "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
32 end
32 end
33
33
34 def render_issue_subject_with_tree(issue)
34 def render_issue_subject_with_tree(issue)
35 s = ''
35 s = ''
36 issue.ancestors.each do |ancestor|
36 issue.ancestors.each do |ancestor|
37 s << '<div>' + content_tag('p', link_to_issue(ancestor))
37 s << '<div>' + content_tag('p', link_to_issue(ancestor))
38 end
38 end
39 s << '<div>' + content_tag('h3', h(issue.subject))
39 s << '<div>' + content_tag('h3', h(issue.subject))
40 s << '</div>' * (issue.ancestors.size + 1)
40 s << '</div>' * (issue.ancestors.size + 1)
41 s
41 s
42 end
42 end
43
43
44 def render_descendants_tree(issue)
44 def render_descendants_tree(issue)
45 s = '<form><table class="list issues">'
45 s = '<form><table class="list issues">'
46 ancestors = []
46 ancestors = []
47 issue.descendants.sort_by(&:lft).each do |child|
47 issue.descendants.sort_by(&:lft).each do |child|
48 level = child.level - issue.level - 1
48 level = child.level - issue.level - 1
49 s << content_tag('tr',
49 s << content_tag('tr',
50 content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') +
50 content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') +
51 content_tag('td', link_to_issue(child, :truncate => 60), :class => 'subject',
51 content_tag('td', link_to_issue(child, :truncate => 60), :class => 'subject',
52 :style => "padding-left: #{level * 20}px") +
52 :style => "padding-left: #{level * 20}px") +
53 content_tag('td', h(child.status)) +
53 content_tag('td', h(child.status)) +
54 content_tag('td', link_to_user(child.assigned_to)) +
54 content_tag('td', link_to_user(child.assigned_to)) +
55 content_tag('td', progress_bar(child.done_ratio, :width => '80px')),
55 content_tag('td', progress_bar(child.done_ratio, :width => '80px')),
56 :class => "issue-#{child.id} hascontextmenu")
56 :class => "issue-#{child.id} hascontextmenu")
57 end
57 end
58 s << '</form></table>'
58 s << '</form></table>'
59 s
59 s
60 end
60 end
61
61
62 def render_custom_fields_rows(issue)
62 def render_custom_fields_rows(issue)
63 return if issue.custom_field_values.empty?
63 return if issue.custom_field_values.empty?
64 ordered_values = []
64 ordered_values = []
65 half = (issue.custom_field_values.size / 2.0).ceil
65 half = (issue.custom_field_values.size / 2.0).ceil
66 half.times do |i|
66 half.times do |i|
67 ordered_values << issue.custom_field_values[i]
67 ordered_values << issue.custom_field_values[i]
68 ordered_values << issue.custom_field_values[i + half]
68 ordered_values << issue.custom_field_values[i + half]
69 end
69 end
70 s = "<tr>\n"
70 s = "<tr>\n"
71 n = 0
71 n = 0
72 ordered_values.compact.each do |value|
72 ordered_values.compact.each do |value|
73 s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0
73 s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0
74 s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(h(show_value(value))) }</td>\n"
74 s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(h(show_value(value))) }</td>\n"
75 n += 1
75 n += 1
76 end
76 end
77 s << "</tr>\n"
77 s << "</tr>\n"
78 s
78 s
79 end
79 end
80
80
81 def sidebar_queries
81 def sidebar_queries
82 unless @sidebar_queries
82 unless @sidebar_queries
83 # User can see public queries and his own queries
83 # User can see public queries and his own queries
84 visible = ARCondition.new(["is_public = ? OR user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
84 visible = ARCondition.new(["is_public = ? OR user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
85 # Project specific queries and global queries
85 # Project specific queries and global queries
86 visible << (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id])
86 visible << (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id])
87 @sidebar_queries = Query.find(:all,
87 @sidebar_queries = Query.find(:all,
88 :select => 'id, name',
88 :select => 'id, name',
89 :order => "name ASC",
89 :order => "name ASC",
90 :conditions => visible.conditions)
90 :conditions => visible.conditions)
91 end
91 end
92 @sidebar_queries
92 @sidebar_queries
93 end
93 end
94
94
95 def show_detail(detail, no_html=false)
95 def show_detail(detail, no_html=false)
96 case detail.property
96 case detail.property
97 when 'attr'
97 when 'attr'
98 field = detail.prop_key.to_s.gsub(/\_id$/, "")
98 field = detail.prop_key.to_s.gsub(/\_id$/, "")
99 label = l(("field_" + field).to_sym)
99 label = l(("field_" + field).to_sym)
100 case
100 case
101 when ['due_date', 'start_date'].include?(detail.prop_key)
101 when ['due_date', 'start_date'].include?(detail.prop_key)
102 value = format_date(detail.value.to_date) if detail.value
102 value = format_date(detail.value.to_date) if detail.value
103 old_value = format_date(detail.old_value.to_date) if detail.old_value
103 old_value = format_date(detail.old_value.to_date) if detail.old_value
104
104
105 when ['project_id', 'status_id', 'tracker_id', 'assigned_to_id', 'priority_id', 'category_id', 'fixed_version_id'].include?(detail.prop_key)
105 when ['project_id', 'status_id', 'tracker_id', 'assigned_to_id', 'priority_id', 'category_id', 'fixed_version_id'].include?(detail.prop_key)
106 value = find_name_by_reflection(field, detail.value)
106 value = find_name_by_reflection(field, detail.value)
107 old_value = find_name_by_reflection(field, detail.old_value)
107 old_value = find_name_by_reflection(field, detail.old_value)
108
108
109 when detail.prop_key == 'estimated_hours'
109 when detail.prop_key == 'estimated_hours'
110 value = "%0.02f" % detail.value.to_f unless detail.value.blank?
110 value = "%0.02f" % detail.value.to_f unless detail.value.blank?
111 old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
111 old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
112
112
113 when detail.prop_key == 'parent_id'
113 when detail.prop_key == 'parent_id'
114 label = l(:field_parent_issue)
114 label = l(:field_parent_issue)
115 value = "##{detail.value}" unless detail.value.blank?
115 value = "##{detail.value}" unless detail.value.blank?
116 old_value = "##{detail.old_value}" unless detail.old_value.blank?
116 old_value = "##{detail.old_value}" unless detail.old_value.blank?
117 end
117 end
118 when 'cf'
118 when 'cf'
119 custom_field = CustomField.find_by_id(detail.prop_key)
119 custom_field = CustomField.find_by_id(detail.prop_key)
120 if custom_field
120 if custom_field
121 label = custom_field.name
121 label = custom_field.name
122 value = format_value(detail.value, custom_field.field_format) if detail.value
122 value = format_value(detail.value, custom_field.field_format) if detail.value
123 old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
123 old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
124 end
124 end
125 when 'attachment'
125 when 'attachment'
126 label = l(:label_attachment)
126 label = l(:label_attachment)
127 end
127 end
128 call_hook(:helper_issues_show_detail_after_setting, {:detail => detail, :label => label, :value => value, :old_value => old_value })
128 call_hook(:helper_issues_show_detail_after_setting, {:detail => detail, :label => label, :value => value, :old_value => old_value })
129
129
130 label ||= detail.prop_key
130 label ||= detail.prop_key
131 value ||= detail.value
131 value ||= detail.value
132 old_value ||= detail.old_value
132 old_value ||= detail.old_value
133
133
134 unless no_html
134 unless no_html
135 label = content_tag('strong', label)
135 label = content_tag('strong', label)
136 old_value = content_tag("i", h(old_value)) if detail.old_value
136 old_value = content_tag("i", h(old_value)) if detail.old_value
137 old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
137 old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
138 if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
138 if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
139 # Link to the attachment if it has not been removed
139 # Link to the attachment if it has not been removed
140 value = link_to_attachment(a)
140 value = link_to_attachment(a)
141 else
141 else
142 value = content_tag("i", h(value)) if value
142 value = content_tag("i", h(value)) if value
143 end
143 end
144 end
144 end
145
145
146 if !detail.value.blank?
146 if !detail.value.blank?
147 case detail.property
147 case detail.property
148 when 'attr', 'cf'
148 when 'attr', 'cf'
149 if !detail.old_value.blank?
149 if !detail.old_value.blank?
150 l(:text_journal_changed, :label => label, :old => old_value, :new => value)
150 l(:text_journal_changed, :label => label, :old => old_value, :new => value)
151 else
151 else
152 l(:text_journal_set_to, :label => label, :value => value)
152 l(:text_journal_set_to, :label => label, :value => value)
153 end
153 end
154 when 'attachment'
154 when 'attachment'
155 l(:text_journal_added, :label => label, :value => value)
155 l(:text_journal_added, :label => label, :value => value)
156 end
156 end
157 else
157 else
158 l(:text_journal_deleted, :label => label, :old => old_value)
158 l(:text_journal_deleted, :label => label, :old => old_value)
159 end
159 end
160 end
160 end
161
161
162 # Find the name of an associated record stored in the field attribute
162 # Find the name of an associated record stored in the field attribute
163 def find_name_by_reflection(field, id)
163 def find_name_by_reflection(field, id)
164 association = Issue.reflect_on_association(field.to_sym)
164 association = Issue.reflect_on_association(field.to_sym)
165 if association
165 if association
166 record = association.class_name.constantize.find_by_id(id)
166 record = association.class_name.constantize.find_by_id(id)
167 return record.name if record
167 return record.name if record
168 end
168 end
169 end
169 end
170
170
171 def issues_to_csv(issues, project = nil)
171 def issues_to_csv(issues, project = nil)
172 ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
172 ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
173 decimal_separator = l(:general_csv_decimal_separator)
173 decimal_separator = l(:general_csv_decimal_separator)
174 export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
174 export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
175 # csv header fields
175 # csv header fields
176 headers = [ "#",
176 headers = [ "#",
177 l(:field_status),
177 l(:field_status),
178 l(:field_project),
178 l(:field_project),
179 l(:field_tracker),
179 l(:field_tracker),
180 l(:field_priority),
180 l(:field_priority),
181 l(:field_subject),
181 l(:field_subject),
182 l(:field_assigned_to),
182 l(:field_assigned_to),
183 l(:field_category),
183 l(:field_category),
184 l(:field_fixed_version),
184 l(:field_fixed_version),
185 l(:field_author),
185 l(:field_author),
186 l(:field_start_date),
186 l(:field_start_date),
187 l(:field_due_date),
187 l(:field_due_date),
188 l(:field_done_ratio),
188 l(:field_done_ratio),
189 l(:field_estimated_hours),
189 l(:field_estimated_hours),
190 l(:field_parent_issue),
190 l(:field_created_on),
191 l(:field_created_on),
191 l(:field_updated_on)
192 l(:field_updated_on)
192 ]
193 ]
193 # Export project custom fields if project is given
194 # Export project custom fields if project is given
194 # otherwise export custom fields marked as "For all projects"
195 # otherwise export custom fields marked as "For all projects"
195 custom_fields = project.nil? ? IssueCustomField.for_all : project.all_issue_custom_fields
196 custom_fields = project.nil? ? IssueCustomField.for_all : project.all_issue_custom_fields
196 custom_fields.each {|f| headers << f.name}
197 custom_fields.each {|f| headers << f.name}
197 # Description in the last column
198 # Description in the last column
198 headers << l(:field_description)
199 headers << l(:field_description)
199 csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
200 csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
200 # csv lines
201 # csv lines
201 issues.each do |issue|
202 issues.each do |issue|
202 fields = [issue.id,
203 fields = [issue.id,
203 issue.status.name,
204 issue.status.name,
204 issue.project.name,
205 issue.project.name,
205 issue.tracker.name,
206 issue.tracker.name,
206 issue.priority.name,
207 issue.priority.name,
207 issue.subject,
208 issue.subject,
208 issue.assigned_to,
209 issue.assigned_to,
209 issue.category,
210 issue.category,
210 issue.fixed_version,
211 issue.fixed_version,
211 issue.author.name,
212 issue.author.name,
212 format_date(issue.start_date),
213 format_date(issue.start_date),
213 format_date(issue.due_date),
214 format_date(issue.due_date),
214 issue.done_ratio,
215 issue.done_ratio,
215 issue.estimated_hours.to_s.gsub('.', decimal_separator),
216 issue.estimated_hours.to_s.gsub('.', decimal_separator),
217 issue.parent_id,
216 format_time(issue.created_on),
218 format_time(issue.created_on),
217 format_time(issue.updated_on)
219 format_time(issue.updated_on)
218 ]
220 ]
219 custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
221 custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
220 fields << issue.description
222 fields << issue.description
221 csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
223 csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
222 end
224 end
223 end
225 end
224 export
226 export
225 end
227 end
226 end
228 end
General Comments 0
You need to be logged in to leave comments. Login now