Project

General

Profile

« Previous | Next » 

Revision 1173

Adds date range filter and pagination on time entries detail view (closes #434).

View differences:

trunk/app/controllers/timelog_controller.rb
23 23
  helper :sort
24 24
  include SortHelper
25 25
  helper :issues
26
  include TimelogHelper
26 27
  
27 28
  def report
28 29
    @available_criterias = { 'version' => {:sql => "#{Issue.table_name}.fixed_version_id",
......
104 105
  def details
105 106
    sort_init 'spent_on', 'desc'
106 107
    sort_update
108

  
109
    @free_period = false
110
    @from, @to = nil, nil
111

  
112
    if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?)
113
      case params[:period].to_s
114
      when 'today'
115
        @from = @to = Date.today
116
      when 'yesterday'
117
        @from = @to = Date.today - 1
118
      when 'current_week'
119
        @from = Date.today - (Date.today.cwday - 1)%7
120
        @to = @from + 6
121
      when 'last_week'
122
        @from = Date.today - 7 - (Date.today.cwday - 1)%7
123
        @to = @from + 6
124
      when '7_days'
125
        @from = Date.today - 7
126
        @to = Date.today
127
      when 'current_month'
128
        @from = Date.civil(Date.today.year, Date.today.month, 1)
129
        @to = (@from >> 1) - 1
130
      when 'last_month'
131
        @from = Date.civil(Date.today.year, Date.today.month, 1) << 1
132
        @to = (@from >> 1) - 1
133
      when '30_days'
134
        @from = Date.today - 30
135
        @to = Date.today
136
      when 'current_year'
137
        @from = Date.civil(Date.today.year, 1, 1)
138
        @to = Date.civil(Date.today.year, 12, 31)
139
      end
140
    elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?))
141
      begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end
142
      begin; @to = params[:to].to_s.to_date unless params[:to].blank?; rescue; end
143
      @free_period = true
144
    else
145
      # default
146
    end
107 147
    
108
    @entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause)
148
    @from, @to = @to, @from if @from && @to && @from > @to
149
    
150
    conditions = nil
151
    if @from
152
      if @to
153
        conditions = ['spent_on BETWEEN ? AND ?', @from, @to]
154
      else
155
        conditions = ['spent_on >= ?', @from]
156
      end
157
    elsif @to
158
      conditions = ['spent_on <= ?', @to]
159
    end
160
    
161
    @owner_id = User.current.id
109 162

  
110
    @total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours }
111
    @owner_id = User.current.id
112
    
113
    send_csv and return if 'csv' == params[:export]    
114
    render :action => 'details', :layout => false if request.xhr?
163
    respond_to do |format|
164
      format.html {
165
        # Paginate results
166
        @entry_count = (@issue ? @issue : @project).time_entries.count(:conditions => conditions)
167
        @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
168
        @entries = (@issue ? @issue : @project).time_entries.find(:all, 
169
                                                                  :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
170
                                                                  :conditions => conditions,
171
                                                                  :order => sort_clause,
172
                                                                  :limit  =>  @entry_pages.items_per_page,
173
                                                                  :offset =>  @entry_pages.current.offset)
174
        @total_hours = (@issue ? @issue : @project).time_entries.sum(:hours, :conditions => conditions).to_f
175
        render :layout => !request.xhr?
176
      }
177
      format.csv {
178
        # Export all entries
179
        @entries = (@issue ? @issue : @project).time_entries.find(:all, 
180
                                                                  :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
181
                                                                  :conditions => conditions,
182
                                                                  :order => sort_clause)
183
        send_data(entries_to_csv(@entries).read, :type => 'text/csv; header=present', :filename => 'timelog.csv')
184
      }
185
    end
115 186
  end
116 187
  
117 188
  def edit
......
141 212
      return false
142 213
    end
143 214
  end
144
  
145
  def send_csv
146
    ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')    
147
    export = StringIO.new
148
    CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
149
      # csv header fields
150
      headers = [l(:field_spent_on),
151
                 l(:field_user),
152
                 l(:field_activity),
153
                 l(:field_issue),
154
                 l(:field_tracker),
155
                 l(:field_subject),
156
                 l(:field_hours),
157
                 l(:field_comments)
158
                 ]
159
      csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
160
      # csv lines
161
      @entries.each do |entry|
162
        fields = [l_date(entry.spent_on),
163
                  entry.user,
164
                  entry.activity,
165
                  (entry.issue ? entry.issue.id : nil),
166
                  (entry.issue ? entry.issue.tracker : nil),
167
                  (entry.issue ? entry.issue.subject : nil),
168
                  entry.hours,
169
                  entry.comments
170
                  ]
171
        csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
172
      end
173
    end
174
    export.rewind
175
    send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
176
  end
177 215
end
trunk/app/helpers/application_helper.rb
90 90
    include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
91 91
  end
92 92
  
93
  def html_hours(text)
94
    text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
95
  end
96
  
93 97
  def authoring(created, author)
94 98
    time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
95 99
    l(:label_added_time_by, author || 'Anonymous', time_tag)
trunk/app/helpers/sort_helper.rb
108 108
    end
109 109
    caption = titleize(Inflector::humanize(column)) unless caption
110 110
    
111
    url = {:sort_key => column, :sort_order => order, :status => params[:status], 
112
                                                      :issue_id => params[:issue_id], 
113
                                                      :project_id => params[:project_id]}
111
    sort_options = { :sort_key => column, :sort_order => order }
112
    # don't reuse params if filters are present
113
    url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
114 114
    
115 115
    link_to_remote(caption,
116
                  {:update => "content", :url => url},
117
                  {:href => url_for(url)}) +
116
                  {:update => "content", :url => url_options},
117
                  {:href => url_for(url_options)}) +
118 118
    (icon ? nbsp(2) + image_tag(icon) : '')
119 119
  end
120 120

  
trunk/app/helpers/timelog_helper.rb
27 27
    end
28 28
    sum
29 29
  end
30
  
31
  def options_for_period_select(value)
32
    options_for_select([[l(:label_all_time), 'all'],
33
                        [l(:label_today), 'today'],
34
                        [l(:label_yesterday), 'yesterday'],
35
                        [l(:label_this_week), 'current_week'],
36
                        [l(:label_last_week), 'last_week'],
37
                        [l(:label_last_n_days, 7), '7_days'],
38
                        [l(:label_this_month), 'current_month'],
39
                        [l(:label_last_month), 'last_month'],
40
                        [l(:label_last_n_days, 30), '30_days'],
41
                        [l(:label_this_year), 'current_year']],
42
                        value)
43
  end
44
  
45
  def entries_to_csv(entries)
46
    ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')    
47
    export = StringIO.new
48
    CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
49
      # csv header fields
50
      headers = [l(:field_spent_on),
51
                 l(:field_user),
52
                 l(:field_activity),
53
                 l(:field_issue),
54
                 l(:field_tracker),
55
                 l(:field_subject),
56
                 l(:field_hours),
57
                 l(:field_comments)
58
                 ]
59
      csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
60
      # csv lines
61
      entries.each do |entry|
62
        fields = [l_date(entry.spent_on),
63
                  entry.user,
64
                  entry.activity,
65
                  (entry.issue ? entry.issue.id : nil),
66
                  (entry.issue ? entry.issue.tracker : nil),
67
                  (entry.issue ? entry.issue.subject : nil),
68
                  entry.hours,
69
                  entry.comments
70
                  ]
71
        csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
72
      end
73
    end
74
    export.rewind
75
    export
76
  end
30 77
end
trunk/app/models/time_entry.rb
46 46
    self.tyear = spent_on ? spent_on.year : nil
47 47
    self.tmonth = spent_on ? spent_on.month : nil
48 48
    self.tweek = spent_on ? Date.civil(spent_on.year, spent_on.month, spent_on.day).cweek : nil
49
  end  
49
  end
50
  
51
  # Returns true if the time entry can be edited by usr, otherwise false
52
  def editable_by?(usr)
53
    usr == self.user
54
  end
50 55
end
trunk/app/views/timelog/_list.rhtml
1
<table class="list time-entries">
2
<thead>
3
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
4
<%= sort_header_tag('user_id', :caption => l(:label_member)) %>
5
<%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
6
<%= sort_header_tag('issue_id', :caption => l(:label_issue), :default_order => 'desc') %>
7
<th><%= l(:field_comments) %></th>
8
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
9
<th></th>
10
</thead>
11
<tbody>
12
<% entries.each do |entry| -%>
13
<tr class="time-entry <%= cycle("odd", "even") %>">
14
<td class="spent_on"><%= format_date(entry.spent_on) %></td>
15
<td class="user"><%= entry.user.name %></td>
16
<td class="activity"><%= entry.activity.name %></td>
17
<td class="subject">
18
  <% if entry.issue -%>
19
  <div class="tooltip"><%= link_to_issue entry.issue %>: <%= h(truncate(entry.issue.subject, 50)) -%>
20
  <span class="tip"><%= render_issue_tooltip entry.issue %></span>
21
  </div>
22
  <% end -%>
23
</td>
24
<td class="comments"><%=h entry.comments %></td>
25
<td class="hours"><%= entry.hours %></td>
26
<td align="center"><%= link_to_if_authorized(l(:button_edit), 
27
                                             {:controller => 'timelog', :action => 'edit', :id => entry},
28
                                             :class => 'icon icon-edit') if entry.editable_by?(User.current) %></td>
29
</tr>
30
<% end -%>
31
</tbdoy>
32
</table>
0 33

  
trunk/app/views/timelog/details.rhtml
4 4

  
5 5
<h2><%= l(:label_spent_time) %></h2>
6 6

  
7
<h3><%= link_to(@project.name, {:action => 'details', :project_id => @project}) if @project %>
8
<%= "/ " + link_to_issue(@issue) + h(": #{@issue.subject}") if @issue %></h3>
7
<% if @issue %>
8
<h3><%= link_to(@project.name, {:action => 'details', :project_id => @project}) %> / <%= link_to_issue(@issue) %></h3>
9
<% end %>
9 10

  
10
<h3 class="textright"><%= l(:label_total) %>: <%= lwr(:label_f_hour, @total_hours) %></h3>
11
<% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %>
12
<%= hidden_field_tag 'project_id', params[:project_id] %>
13
<%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %>
11 14

  
12
<% unless @entries.empty? %>
13
<table class="list">
14
<thead>
15
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
16
<%= sort_header_tag('user_id', :caption => l(:label_member)) %>
17
<%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
18
<%= sort_header_tag('issue_id', :caption => l(:label_issue)) %>
19
<th><%= l(:field_comments) %></th>
20
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
21
<th></th>
22
</thead>
23
<tbody>
24
<% @entries.each do |entry| %>
25
<tr class="<%= cycle("odd", "even") %>">
26
<td align="center"><%= format_date(entry.spent_on) %></td>
27
<td align="center"><%= entry.user.name %></td>
28
<td align="center"><%= entry.activity.name %></td>
29
<td>
30
    <% if entry.issue %>
31
    <div class="tooltip">
32
    <%= link_to_issue entry.issue %>: <%= h(truncate(entry.issue.subject, 50)) %>
33
    <span class="tip">
34
    <%= render_issue_tooltip entry.issue %>
35
    </span>		
36
	</div>
37
	<% end %>
38
</td>
39
<td><%=h entry.comments %></td>
40
<td align="center"><strong><%= entry.hours %></strong></td>
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
</tr>
15
<fieldset><legend><%= l(:label_date_range) %></legend>
16
<p>
17
<%= radio_button_tag 'period_type', '1', !@free_period %>
18
<%= select_tag 'period', options_for_period_select(params[:period]),
19
                         :onchange => 'this.form.onsubmit();',
20
                         :onfocus => '$("period_type_1").checked = true;' %>
21
</p>
22
<p>
23
<%= radio_button_tag 'period_type', '2', @free_period %>
24
<%= l(:label_date_from) %>
25
<%= text_field_tag 'from', @from, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('from') %>
26
<%= l(:label_date_to) %>
27
<%= text_field_tag 'to', @to, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('to') %>
28
<%= submit_tag l(:button_submit), :name => nil, :onclick => '$("period_type_2").checked = true;' %>
29
</p>
30
</fieldset>
43 31
<% end %>
44
</tbdoy>
45
</table>
46 32

  
33
<div class="total-hours">
34
<p><%= l(:label_total) %>: <%= html_hours(lwr(:label_f_hour, @total_hours)) %></p>
35
</div>
36

  
37
<% unless @entries.empty? %>
38
<%= render :partial => 'list', :locals => { :entries => @entries }%>
47 39
<div class="contextual">
48
<%= l(:label_export_to) %>
49
<%= link_to 'CSV', params.update(:export => 'csv'), :class => 'icon icon-csv' %>
40
    <%= l(:label_export_to) %>
41
    <%= link_to 'CSV', params.merge(:format => 'csv'), :class => 'icon icon-csv' %>
50 42
</div>
51
<% end %>
43
<p class="pagination"><%= pagination_links_full @entry_pages, @entry_count %></p>
44
<% end %>
45

  
46
<% content_for :header_tags do %>
47
    <%= javascript_include_tag 'calendar/calendar' %>
48
    <%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
49
    <%= javascript_include_tag 'calendar/calendar-setup' %>
50
    <%= stylesheet_link_tag 'calendar' %>
51
<% end %>
trunk/lang/bg.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/cs.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/de.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/en.yml
362 362
label_in_more_than: in more than
363 363
label_in: in
364 364
label_today: today
365
label_all_time: all time
366
label_yesterday: yesterday
365 367
label_this_week: this week
368
label_last_week: last week
369
label_last_n_days: last %d days
370
label_this_month: this month
371
label_last_month: last month
372
label_this_year: this year
373
label_date_range: Date range
366 374
label_less_than_ago: less than days ago
367 375
label_more_than_ago: more than days ago
368 376
label_ago: days ago
trunk/lang/es.yml
595 595
label_plugins: Plugins
596 596
label_ldap_authentication: LDAP authentication
597 597
label_downloads_abbr: D/L
598
label_this_month: this month
599
label_last_n_days: last %d days
600
label_all_time: all time
601
label_this_year: this year
602
label_date_range: Date range
603
label_last_week: last week
604
label_yesterday: yesterday
605
label_last_month: last month
trunk/lang/fi.yml
596 596
label_plugins: Plugins
597 597
label_ldap_authentication: LDAP authentication
598 598
label_downloads_abbr: D/L
599
label_this_month: this month
600
label_last_n_days: last %d days
601
label_all_time: all time
602
label_this_year: this year
603
label_date_range: Date range
604
label_last_week: last week
605
label_yesterday: yesterday
606
label_last_month: last month
trunk/lang/fr.yml
362 362
label_in_more_than: dans plus de
363 363
label_in: dans
364 364
label_today: aujourd'hui
365
label_all_time: toute la période
366
label_yesterday: hier
365 367
label_this_week: cette semaine
368
label_last_week: la semaine dernière
369
label_last_n_days: les %d derniers jours
370
label_this_month: ce mois-ci
371
label_last_month: le mois dernier
372
label_this_year: cette année
373
label_date_range: Période
366 374
label_less_than_ago: il y a moins de
367 375
label_more_than_ago: il y a plus de
368 376
label_ago: il y a
trunk/lang/he.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/it.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/ja.yml
593 593
label_plugins: Plugins
594 594
label_ldap_authentication: LDAP authentication
595 595
label_downloads_abbr: D/L
596
label_this_month: this month
597
label_last_n_days: last %d days
598
label_all_time: all time
599
label_this_year: this year
600
label_date_range: Date range
601
label_last_week: last week
602
label_yesterday: yesterday
603
label_last_month: last month
trunk/lang/ko.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/lt.yml
593 593
label_plugins: Plugins
594 594
label_ldap_authentication: LDAP authentication
595 595
label_downloads_abbr: D/L
596
label_this_month: this month
597
label_last_n_days: last %d days
598
label_all_time: all time
599
label_this_year: this year
600
label_date_range: Date range
601
label_last_week: last week
602
label_yesterday: yesterday
603
label_last_month: last month
trunk/lang/nl.yml
593 593
label_plugins: Plugins
594 594
label_ldap_authentication: LDAP authentication
595 595
label_downloads_abbr: D/L
596
label_this_month: this month
597
label_last_n_days: last %d days
598
label_all_time: all time
599
label_this_year: this year
600
label_date_range: Date range
601
label_last_week: last week
602
label_yesterday: yesterday
603
label_last_month: last month
trunk/lang/pl.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/pt-br.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/pt.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/ro.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/ru.yml
596 596
label_plugins: Plugins
597 597
label_ldap_authentication: LDAP authentication
598 598
label_downloads_abbr: D/L
599
label_this_month: this month
600
label_last_n_days: last %d days
601
label_all_time: all time
602
label_this_year: this year
603
label_date_range: Date range
604
label_last_week: last week
605
label_yesterday: yesterday
606
label_last_month: last month
trunk/lang/sr.yml
593 593
label_plugins: Plugins
594 594
label_ldap_authentication: LDAP authentication
595 595
label_downloads_abbr: D/L
596
label_this_month: this month
597
label_last_n_days: last %d days
598
label_all_time: all time
599
label_this_year: this year
600
label_date_range: Date range
601
label_last_week: last week
602
label_yesterday: yesterday
603
label_last_month: last month
trunk/lang/sv.yml
593 593
label_plugins: Plugins
594 594
label_ldap_authentication: LDAP authentication
595 595
label_downloads_abbr: D/L
596
label_this_month: this month
597
label_last_n_days: last %d days
598
label_all_time: all time
599
label_this_year: this year
600
label_date_range: Date range
601
label_last_week: last week
602
label_yesterday: yesterday
603
label_last_month: last month
trunk/lang/uk.yml
594 594
label_plugins: Plugins
595 595
label_ldap_authentication: LDAP authentication
596 596
label_downloads_abbr: D/L
597
label_this_month: this month
598
label_last_n_days: last %d days
599
label_all_time: all time
600
label_this_year: this year
601
label_date_range: Date range
602
label_last_week: last week
603
label_yesterday: yesterday
604
label_last_month: last month
trunk/lang/zh-tw.yml
592 592
label_plugins: Plugins
593 593
label_ldap_authentication: LDAP authentication
594 594
label_downloads_abbr: D/L
595
label_this_month: this month
596
label_last_n_days: last %d days
597
label_all_time: all time
598
label_this_year: this year
599
label_date_range: Date range
600
label_last_week: last week
601
label_yesterday: yesterday
602
label_last_month: last month
trunk/lang/zh.yml
595 595
label_plugins: Plugins
596 596
label_ldap_authentication: LDAP authentication
597 597
label_downloads_abbr: D/L
598
label_this_month: this month
599
label_last_n_days: last %d days
600
label_all_time: all time
601
label_this_year: this year
602
label_date_range: Date range
603
label_last_week: last week
604
label_yesterday: yesterday
605
label_last_month: last month
trunk/public/stylesheets/application.css
110 110
tr.user.locked, tr.user.registered { color: #aaa; }
111 111
tr.user.locked a, tr.user.registered a { color: #aaa; }
112 112

  
113
tr.time-entry { text-align: center; white-space: nowrap; }
114
tr.time-entry td.subject, tr.time-entry td.comments { text-align: left; }
115
tr.time-entry td.hours { text-align: right; font-weight: bold; padding-right: 0.6em; }
116

  
113 117
table.list tbody tr:hover { background-color:#ffffdd; }
114 118
table td {padding:2px;}
115 119
table p {margin:0;}
......
169 173
div#roadmap .wiki h1 { font-size: 120%; }
170 174
div#roadmap .wiki h2 { font-size: 110%; }
171 175

  
176
div.total-hours { text-align: left; font-size: 110%; font-weight: bold; }
177
div.total-hours span.hours-int { font-size: 120%; }
178

  
172 179
.autoscroll {overflow-x: auto; padding:1px; width:100%; margin-bottom: 1.2em;}
173 180
#user_firstname, #user_lastname, #user_mail, #my_account_form select { width: 90%; }
174 181

  
trunk/public/stylesheets/calendar.css
6 6
    margin-left: 4px;
7 7
}
8 8

  
9
div.calendar { position: relative; z-index: 15;}
9
div.calendar { position: relative; z-index: 30;}
10 10

  
11 11
.calendar, .calendar table {
12 12
  border: 1px solid #556;
trunk/test/fixtures/time_entries.yml
21 21
  comments: ""
22 22
  updated_on: 2007-03-23 14:11:04 +01:00
23 23
  activity_id: 8
24
  spent_on: 2007-03-23
24
  spent_on: 2007-03-12
25 25
  issue_id: 1
26 26
  id: 2
27 27
  hours: 150.0
trunk/test/functional/timelog_controller_test.rb
22 22
class TimelogController; def rescue_action(e) raise e end; end
23 23

  
24 24
class TimelogControllerTest < Test::Unit::TestCase
25
  fixtures :time_entries, :issues
25
  fixtures :projects, :issues, :time_entries, :users, :trackers, :enumerations, :issue_statuses
26 26

  
27 27
  def setup
28 28
    @controller = TimelogController.new
......
49 49
    assert_template 'report'
50 50
    assert_not_nil assigns(:hours)
51 51
  end
52
  
53
  def test_details_at_project_level
54
    get :details, :project_id => 1
55
    assert_response :success
56
    assert_template 'details'
57
    assert_not_nil assigns(:entries)
58
    assert_equal 3, assigns(:entries).size
59
    assert_not_nil assigns(:total_hours)
60
    assert_equal 155.25, assigns(:total_hours)
61
    # display all time by default
62
    assert_nil assigns(:from)
63
    assert_nil assigns(:to)
64
  end
65
  
66
  def test_details_at_project_level_with_date_range
67
    get :details, :project_id => 1, :from => '2007-03-20', :to => '2007-04-30'
68
    assert_response :success
69
    assert_template 'details'
70
    assert_not_nil assigns(:entries)
71
    assert_equal 2, assigns(:entries).size
72
    assert_not_nil assigns(:total_hours)
73
    assert_equal 5.25, assigns(:total_hours)
74
    assert_equal '2007-03-20'.to_date, assigns(:from)
75
    assert_equal '2007-04-30'.to_date, assigns(:to)
76
  end
77

  
78
  def test_details_at_project_level_with_period
79
    get :details, :project_id => 1, :period => '7_days'
80
    assert_response :success
81
    assert_template 'details'
82
    assert_not_nil assigns(:entries)
83
    assert_not_nil assigns(:total_hours)
84
    assert_equal Date.today - 7, assigns(:from)
85
    assert_equal Date.today, assigns(:to)
86
  end
87
  
88
  def test_details_at_issue_level
89
    get :details, :issue_id => 1
90
    assert_response :success
91
    assert_template 'details'
92
    assert_not_nil assigns(:entries)
93
    assert_equal 2, assigns(:entries).size
94
    assert_not_nil assigns(:total_hours)
95
    assert_equal 154.25, assigns(:total_hours)
96
    # display all time by default
97
    assert_nil assigns(:from)
98
    assert_nil assigns(:to)
99
  end
52 100
end

Also available in: Unified diff