##// END OF EJS Templates
Added issue subject to the time entries view and subject + tracker to the csv export (#616). Default order on date column set to desc....
Jean-Philippe Lang -
r1128:4dc7f662e3d9
parent child
Show More
@@ -1,173 +1,177
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 TimelogController < ApplicationController
19 19 layout 'base'
20 20 menu_item :issues
21 21 before_filter :find_project, :authorize
22 22
23 23 helper :sort
24 24 include SortHelper
25 25 helper :issues
26 26
27 27 def report
28 28 @available_criterias = { 'version' => {:sql => "#{Issue.table_name}.fixed_version_id",
29 29 :values => @project.versions,
30 30 :label => :label_version},
31 31 'category' => {:sql => "#{Issue.table_name}.category_id",
32 32 :values => @project.issue_categories,
33 33 :label => :field_category},
34 34 'member' => {:sql => "#{TimeEntry.table_name}.user_id",
35 35 :values => @project.users,
36 36 :label => :label_member},
37 37 'tracker' => {:sql => "#{Issue.table_name}.tracker_id",
38 38 :values => Tracker.find(:all),
39 39 :label => :label_tracker},
40 40 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id",
41 41 :values => Enumeration::get_values('ACTI'),
42 42 :label => :label_activity}
43 43 }
44 44
45 45 @criterias = params[:criterias] || []
46 46 @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria}
47 47 @criterias.uniq!
48 48
49 49 @columns = (params[:period] && %w(year month week).include?(params[:period])) ? params[:period] : 'month'
50 50
51 51 if params[:date_from]
52 52 begin; @date_from = params[:date_from].to_date; rescue; end
53 53 end
54 54 if params[:date_to]
55 55 begin; @date_to = params[:date_to].to_date; rescue; end
56 56 end
57 57 @date_from ||= Date.civil(Date.today.year, 1, 1)
58 58 @date_to ||= (Date.civil(Date.today.year, Date.today.month, 1) >> 1) - 1
59 59
60 60 unless @criterias.empty?
61 61 sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
62 62 sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ')
63 63
64 64 sql = "SELECT #{sql_select}, tyear, tmonth, tweek, SUM(hours) AS hours"
65 65 sql << " FROM #{TimeEntry.table_name} LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id"
66 66 sql << " WHERE #{TimeEntry.table_name}.project_id = %s" % @project.id
67 67 sql << " AND spent_on BETWEEN '%s' AND '%s'" % [ActiveRecord::Base.connection.quoted_date(@date_from.to_time), ActiveRecord::Base.connection.quoted_date(@date_to.to_time)]
68 68 sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek"
69 69
70 70 @hours = ActiveRecord::Base.connection.select_all(sql)
71 71
72 72 @hours.each do |row|
73 73 case @columns
74 74 when 'year'
75 75 row['year'] = row['tyear']
76 76 when 'month'
77 77 row['month'] = "#{row['tyear']}-#{row['tmonth']}"
78 78 when 'week'
79 79 row['week'] = "#{row['tyear']}-#{row['tweek']}"
80 80 end
81 81 end
82 82 end
83 83
84 84 @periods = []
85 85 date_from = @date_from
86 86 # 100 columns max
87 87 while date_from < @date_to && @periods.length < 100
88 88 case @columns
89 89 when 'year'
90 90 @periods << "#{date_from.year}"
91 91 date_from = date_from >> 12
92 92 when 'month'
93 93 @periods << "#{date_from.year}-#{date_from.month}"
94 94 date_from = date_from >> 1
95 95 when 'week'
96 96 @periods << "#{date_from.year}-#{date_from.cweek}"
97 97 date_from = date_from + 7
98 98 end
99 99 end
100 100
101 101 render :layout => false if request.xhr?
102 102 end
103 103
104 104 def details
105 105 sort_init 'spent_on', 'desc'
106 106 sort_update
107 107
108 108 @entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause)
109 109
110 110 @total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours }
111 111 @owner_id = User.current.id
112 112
113 113 send_csv and return if 'csv' == params[:export]
114 114 render :action => 'details', :layout => false if request.xhr?
115 115 end
116 116
117 117 def edit
118 118 render_404 and return if @time_entry && @time_entry.user != User.current
119 119 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
120 120 @time_entry.attributes = params[:time_entry]
121 121 if request.post? and @time_entry.save
122 122 flash[:notice] = l(:notice_successful_update)
123 123 redirect_to :action => 'details', :project_id => @time_entry.project, :issue_id => @time_entry.issue
124 124 return
125 125 end
126 126 @activities = Enumeration::get_values('ACTI')
127 127 end
128 128
129 129 private
130 130 def find_project
131 131 if params[:id]
132 132 @time_entry = TimeEntry.find(params[:id])
133 133 @project = @time_entry.project
134 134 elsif params[:issue_id]
135 135 @issue = Issue.find(params[:issue_id])
136 136 @project = @issue.project
137 137 elsif params[:project_id]
138 138 @project = Project.find(params[:project_id])
139 139 else
140 140 render_404
141 141 return false
142 142 end
143 143 end
144 144
145 145 def send_csv
146 146 ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
147 147 export = StringIO.new
148 148 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
149 149 # csv header fields
150 150 headers = [l(:field_spent_on),
151 151 l(:field_user),
152 152 l(:field_activity),
153 153 l(:field_issue),
154 l(:field_tracker),
155 l(:field_subject),
154 156 l(:field_hours),
155 157 l(:field_comments)
156 158 ]
157 159 csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
158 160 # csv lines
159 161 @entries.each do |entry|
160 162 fields = [l_date(entry.spent_on),
161 entry.user.name,
162 entry.activity.name,
163 entry.user,
164 entry.activity,
163 165 (entry.issue ? entry.issue.id : nil),
166 (entry.issue ? entry.issue.tracker : nil),
167 (entry.issue ? entry.issue.subject : nil),
164 168 entry.hours,
165 169 entry.comments
166 170 ]
167 171 csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
168 172 end
169 173 end
170 174 export.rewind
171 175 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
172 176 end
173 177 end
@@ -1,51 +1,51
1 1 <div class="contextual">
2 2 <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time' %>
3 3 </div>
4 4
5 5 <h2><%= l(:label_spent_time) %></h2>
6 6
7 7 <h3><%= link_to(@project.name, {:action => 'details', :project_id => @project}) if @project %>
8 8 <%= "/ " + link_to_issue(@issue) + h(": #{@issue.subject}") if @issue %></h3>
9 9
10 10 <h3 class="textright"><%= l(:label_total) %>: <%= lwr(:label_f_hour, @total_hours) %></h3>
11 11
12 12 <% unless @entries.empty? %>
13 13 <table class="list">
14 14 <thead>
15 <%= sort_header_tag('spent_on', :caption => l(:label_date)) %>
15 <%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
16 16 <%= sort_header_tag('user_id', :caption => l(:label_member)) %>
17 17 <%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
18 18 <%= sort_header_tag('issue_id', :caption => l(:label_issue)) %>
19 19 <th><%= l(:field_comments) %></th>
20 20 <%= sort_header_tag('hours', :caption => l(:field_hours)) %>
21 21 <th></th>
22 22 </thead>
23 23 <tbody>
24 24 <% @entries.each do |entry| %>
25 25 <tr class="<%= cycle("odd", "even") %>">
26 26 <td align="center"><%= format_date(entry.spent_on) %></td>
27 27 <td align="center"><%= entry.user.name %></td>
28 28 <td align="center"><%= entry.activity.name %></td>
29 <td align="center">
29 <td>
30 30 <% if entry.issue %>
31 31 <div class="tooltip">
32 <%= link_to_issue entry.issue %>
32 <%= link_to_issue entry.issue %>: <%= h(truncate(entry.issue.subject, 50)) %>
33 33 <span class="tip">
34 34 <%= render_issue_tooltip entry.issue %>
35 35 </span>
36 36 </div>
37 37 <% end %>
38 38 </td>
39 39 <td><%=h entry.comments %></td>
40 40 <td align="center"><strong><%= entry.hours %></strong></td>
41 41 <td align="center"><%= link_to_if_authorized(l(:button_edit), {:controller => 'timelog', :action => 'edit', :id => entry}, :class => "icon icon-edit") if entry.user_id == @owner_id %></td>
42 42 </tr>
43 43 <% end %>
44 44 </tbdoy>
45 45 </table>
46 46
47 47 <div class="contextual">
48 48 <%= l(:label_export_to) %>
49 49 <%= link_to 'CSV', params.update(:export => 'csv'), :class => 'icon icon-csv' %>
50 50 </div>
51 51 <% end %> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now