backlog 0.21.0 → 0.21.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,17 @@
1
+ == 0.21.1 2008-02-04
2
+
3
+ === Features
4
+
5
+ * Added link from weekly work sheet summary to details view with editing option.
6
+
7
+ === Fixes
8
+
9
+ * Changed to nag for work locks at 10am instead of every 24 hours after server startup.
10
+ * Added localizations for Lock/Unlock operations.
11
+ * Fixed bug when updating work records without tasks.
12
+ * Changed formatting of week total of work account to two decimals in the weekly work sheet.
13
+ * Fixed editing in weekly work sheet details view.
14
+
1
15
  == 0.21.0 2008-02-02
2
16
 
3
17
  === Features
data/Rakefile CHANGED
@@ -46,6 +46,8 @@ task :release_all do
46
46
  Rake::Task[:post_news].invoke
47
47
  end
48
48
 
49
+ # Remember to set timeout in /usr/lib/ruby/gems/1.8/gems/rubyforge-0.4.4/lib/http-access2.rb
50
+ # @send_timeout = 3600
49
51
  desc 'Release the application as a Java EE WAR file to RubyForge'
50
52
  task :release_war do
51
53
  FileUtils.rm_rf 'WEB-INF' if File.exists? 'WEB-INF'
@@ -73,13 +73,18 @@ class WorksController < ApplicationController
73
73
  @work.attributes = params[:work]
74
74
  @estimate = Estimate.new(params[:estimate])
75
75
  @work_accounts = WorkAccount.find(:all)
76
- @tasks = [@work.task] + Task.find_open
76
+ @tasks = Task.find_open
77
+ @tasks.unshift @work.task if @work.task
77
78
  @users = User.find(:all)
78
79
  end
79
80
 
80
81
  def update
81
82
  if update_work
82
- back_or_redirect_to :controller => 'periods', :action => 'show', :id => @work.task.period, :task_id => @work.task.id
83
+ if @work.task
84
+ back_or_redirect_to :controller => 'periods', :action => 'show', :id => @work.task.period, :task_id => @work.task.id
85
+ else
86
+ back_or_redirect_to :controller => 'welcome', :action => 'index'
87
+ end
83
88
  else
84
89
  @task = @work.task
85
90
  edit
@@ -199,7 +204,7 @@ class WorksController < ApplicationController
199
204
 
200
205
  render :partial => 'description_list'
201
206
  end
202
-
207
+
203
208
  def calculate_hours
204
209
  calculated_duration = (Time.parse(params[:completed_at]) - Time.parse(params[:started_at]))
205
210
  new_value = '%2d:%02d' % [calculated_duration / 3600, (calculated_duration % 3600) / 60]
@@ -19,9 +19,9 @@ class WorkLockNagger
19
19
  loop do
20
20
  puts "Nagging"
21
21
  begin
22
- p late_work_locks = WorkLock.find(
23
- :all,
24
- :conditions => ["end_on < ? and not exists (select id from work_locks wl2 where wl2.user_id = work_locks.user_id and wl2.end_on > work_locks.end_on)", Date.today ])
22
+ late_work_locks = WorkLock.find(
23
+ :all,
24
+ :conditions => ["end_on < ? and not exists (select id from work_locks wl2 where wl2.user_id = work_locks.user_id and wl2.end_on > work_locks.end_on)", Date.today ])
25
25
  late_users = late_work_locks.map{|wl| wl.user}.uniq
26
26
  late_users.each do |u|
27
27
  missing_date = (u.work_locks.last.end_on + 7)
@@ -29,11 +29,15 @@ class WorkLockNagger
29
29
  week = missing_date.cweek
30
30
  WorkLockNotify.deliver_nag(u, week, url + "/#{year}/#{week}")
31
31
  end
32
+ now = Time.now
33
+ next_nag_time = Time.local(now.year, now.month, now.hour < 10 ? now.day : now.day + 1, 10, 0, 0)
34
+ sleep_duration = next_nag_time - now
35
+ puts "Sleeping #{sleep_duration.to_i / 3600} hours #{(sleep_duration.to_i % 3600) / 60} minutes and #{sleep_duration.to_i % 60} seconds."
36
+ sleep sleep_duration
32
37
  rescue Exception => e
33
38
  p e
34
39
  end
35
40
  puts "Nag ends"
36
- sleep 24.hours
37
41
  end
38
42
  end
39
43
 
@@ -0,0 +1,20 @@
1
+ <div style="float: left"><%=link_to(image_tag('arrow_left.png'), :year => (@week > 1 ? @year : @year - 1), :week => (@week > 1 ? @week - 1 : 52))%></div>
2
+ <div style="float: right"><%=link_to(image_tag('arrow_right.png'), :year => (@week < 52 ? @year : @year + 1), :week => (@week < 52 ? @week + 1 : 1))%></div>
3
+
4
+ <div align="right">
5
+ <% lock_action = @lock ? :unlock : :lock %>
6
+ [<%=link_to l(lock_action), with_detour(:controller => 'work_locks', :action => lock_action, :year => @year, :week => @week) %>]
7
+ <%unless controller.action_name == 'weekly_work_sheet'%>
8
+ [<%=link_to l(:details), :action => :weekly_work_sheet, :year => @year, :week => @week %>]
9
+ <% end %>
10
+ <%unless controller.action_name == 'weekly_work_sheet_by_work_account'%>
11
+ [<%=link_to l(:totals), :action => :weekly_work_sheet_by_work_account, :year => @year, :week => @week %>]
12
+ <% end %>
13
+ <% if @lock %>
14
+ [<%=link_to l(:spreadsheet), :action => :timeliste, :year => @year, :week => @week %>]
15
+ <% else %>
16
+ [<%=detour_to l(:new_work), :controller => 'works', :action => :new %>]
17
+ <% end %>
18
+ </div>
19
+
20
+ <br clear="all" />
@@ -5,22 +5,9 @@
5
5
  <% invoicing = @rows.find {|r| r.find {|w| w && w.work_account.enable_invoicing?}} %>
6
6
  <% columns = 2 + (track_times ? 1 : 0) + (invoicing ? 1 : 0) %>
7
7
 
8
- <div style="float: left"><%=link_to(image_tag('arrow_left.png'), :year => (@week > 1 ? @year : @year - 1), :week => (@week > 1 ? @week - 1 : 52))%></div>
9
- <div style="float: right"><%=link_to(image_tag('arrow_right.png'), :year => (@week < 52 ? @year : @year + 1), :week => (@week < 52 ? @week + 1 : 1))%></div>
10
-
11
8
  <h1>Work for week <%=@week%><%=user? ? " for #{user.login}" : ''%></h1>
12
9
 
13
- <div align="right">
14
- <% lock_action = @lock ? :unlock : :lock %>
15
- [<%=link_to l(lock_action), :controller => 'work_locks', :action => lock_action %>]
16
- [<%=detour_to l(:new_work), :controller => 'works', :action => :new %>]
17
- [<%=link_to 'Timeliste', :action => :timeliste, :id => @week %>]
18
- [<%= if params[:with_empty]
19
- link_to 'Hide empty work records'
20
- else
21
- link_to 'Show empty work records', :with_empty => 'yes'
22
- end %>]
23
- </div>
10
+ <%=render :partial => 'weekly_work_sheet_buttons'%>
24
11
 
25
12
  <table border="1">
26
13
  <tr>
@@ -47,47 +34,69 @@ end %>]
47
34
  <% day_totals = Array.new(7, 0) %>
48
35
  <% for row in @rows %>
49
36
  <tr>
50
- <% row.each_with_index do |@work, day| %>
51
- <% if @work %>
52
- <% day_totals[day] += @work.hours %>
53
- <% week_total += @work.hours %>
54
- <td valign="top">
55
- <%=image_detour_to('hammer.png', l(:edit), {:controller => 'works', :action => :edit, :id => @work.id}, {:style => "float: left; border: 1px solid black"}) %>
56
- <!--
57
- <%=detour_to(h(@work.task.period.name), :controller => 'periods', :action => :show, :id => @work.task.period) if @work.task && @work.task.period %>
58
- -->
59
- <%=detour_to(h(@work.work_account.name), :controller => 'work_accounts', :action => :show, :id => @work.work_account_id) %>:
37
+ <% row.each_with_index do |@work, day| %>
38
+ <% if @work %>
39
+ <% day_totals[day] += @work.hours %>
40
+ <% week_total += @work.hours %>
41
+ <td valign="top">
42
+ <%=image_detour_to('hammer.png', l(:edit), {:controller => 'works', :action => :edit, :id => @work.id}, {:style => "float: left"}) %>
43
+ <% if @work.task_id %>
44
+ <%=detour_to(h(@work.task.description), :controller => 'tasks', :action => :edit, :id => @work.task_id)%>
45
+ <% else %>
46
+ <% field_id = "work_#{@work.id}_description" %>
47
+ <%=text_field(:work, :description, :id => field_id, :name => "work_#{@work.id}_description", :class => :task_description, :style => 'width: 8em', :disabled => @lock,
48
+ :onchange => "new Ajax.Updater('#{field_id}', '#{url_for(:action => :update, :id => @work.id)}' + '?work[description]=' + this.value);") %>
49
+ <% end %>
50
+ <br/>
60
51
  <!--
61
- <%=detour_to(h(@work.task.description), :controller => 'tasks', :action => :edit, :id => @work.task_id) if @work.task_id%>
52
+ <%=detour_to(h(@work.task.period.name), :controller => 'periods', :action => :show, :id => @work.task.period) if @work.task && @work.task.period %>
62
53
  -->
63
- </td>
64
- <% if invoicing %>
65
- <td id="invoice_<%=@work.id%>" valign="top">
66
- <%=check_box(:work, :invoice, :onchange => "new Ajax.Updater('invoice_#{@work}', '#{url_for(:action => :set_work_invoice, :id => @work)}' + '?value=' + this.checked);", :disabled => @lock) if @work.work_account.enable_invoicing? %>
67
- </td>
68
- <% end %>
69
- <% if track_times %>
70
- <td align="left" valign="top"><%=text_field(:work, :started_at_time, :class => :task_time, :disabled => @lock) %> -
71
- <%=text_field(:work, :completed_at_time, :class => :task_time, :disabled => @lock) %></td>
54
+ <%=detour_to(h(@work.work_account.name), :controller => 'work_accounts', :action => :show, :id => @work.work_account_id) %>
55
+ </td>
56
+ <% if invoicing %>
57
+ <td id="invoice_<%=@work.id%>" valign="top">
58
+ <% form_id = "work_#{@work.id}_invoice_form" %>
59
+ <% field_id = "work_#{@work.id}_invoice" %>
60
+ <%=check_box(:work, :invoice, :id => field_id, :name => field_id, :onchange => "new Ajax.Updater('invoice_#{@work}', '#{url_for(:action => :set_work_invoice, :id => @work)}' + '?value=' + this.checked);", :disabled => @lock) if @work.work_account.enable_invoicing? %>
61
+ </td>
62
+ <% end %>
63
+ <% if track_times %>
64
+ <td align="left" valign="top">
65
+ <% form_id = "work_#{@work.id}_time_form" %>
66
+ <% field_id = "work_#{@work.id}_started_at_time" %>
67
+ <form id="<%=form_id%>">
68
+ <%=text_field(:work, :started_at_time, :class => :task_time, :disabled => @lock,
69
+ :onchange => "new Ajax.Updater('#{field_id}', '#{url_for(:action => :update, :id => @work.id)}' + '?work[started_at_time]=' + this.value);") %> -
70
+ <%=text_field(:work, :completed_at_time, :class => :task_time, :disabled => @lock,
71
+ :onchange => "new Ajax.Updater('work_#{@work.id}_completed_at_time', '#{url_for(:action => :update, :id => @work.id)}' + '?work[completed_at_time]=' + this.value);") %>
72
+ </form>
73
+ </td>
74
+ <% end %>
75
+ <td align="right" valign="top">
76
+ <% form_id = "work_#{@work.id}_hours_form" %>
77
+ <% field_id = "work_#{@work.id}_hours_time" %>
78
+ <form id="<%=form_id%>">
79
+ <%=text_field(:work, :hours_time, :value => '%d:%02d' % [@work.hours , 60 * @work.hours % 60], :class => 'task_hours', :disabled => @lock,
80
+ :onchange => "new Ajax.Updater('#{field_id}', '#{url_for(:action => :update, :id => @work.id)}' + '?work[hours_time]=' + this.value);") %>
81
+ </form>
82
+ </td>
83
+ <% else %>
84
+ <td/>
85
+ <% if invoicing %>
86
+ <td/>
87
+ <% end %>
88
+ <% if track_times %>
89
+ <td/>
90
+ <% end %>
91
+ <td/>
72
92
  <% end %>
73
- <td align="right" valign="top"><%=text_field(:work, :hours, :value => '%.2f' % @work.hours, :class => 'task_hours') %></td>
74
- <% else %>
75
- <td/>
76
- <% if invoicing %>
77
- <td/>
78
- <% end %>
79
- <% if track_times %>
80
- <td/>
81
- <% end %>
82
- <td/>
83
93
  <% end %>
84
- <% end %>
85
94
  </tr>
86
95
  <% end %>
87
96
  <tr>
88
- <% (0..6).each do |day| %>
89
- <th class="hours" colspan="<%=columns%>"><%='%.2f' % day_totals[day] if day_totals[day] > 0%></th>
90
- <% end %>
97
+ <% (0..6).each do |day| %>
98
+ <th class="hours" colspan="<%=columns%>"><%='%.2f' % day_totals[day] if day_totals[day] > 0%></th>
99
+ <% end %>
91
100
  <th class="hours"><%= '%.2f' % week_total %></th>
92
101
  </tr>
93
102
  </table>
@@ -3,20 +3,7 @@
3
3
  <div id="spotlight">
4
4
  <% columns = 2 %>
5
5
 
6
- <div style="float: left"><%=link_to(image_tag('arrow_left.png'), :year => (@week > 1 ? @year : @year - 1), :week => (@week > 1 ? @week - 1 : 52))%></div>
7
- <div style="float: right"><%=link_to(image_tag('arrow_right.png'), :year => (@week < 52 ? @year : @year + 1), :week => (@week < 52 ? @week + 1 : 1))%></div>
8
-
9
- <div align="right">
10
- <% lock_action = @lock ? :unlock : :lock %>
11
- [<%=link_to l(lock_action), with_detour(:controller => 'work_locks', :action => lock_action, :year => @year, :week => @week) %>]
12
- <% if @lock %>
13
- [<%=link_to l(:spreadsheet), :action => :timeliste, :year => @year, :week => @week %>]
14
- <% else %>
15
- [<%=detour_to l(:new_work), :controller => 'works', :action => :new %>]
16
- <% end %>
17
- </div>
18
-
19
- <br clear="all" />
6
+ <%=render :partial => 'weekly_work_sheet_buttons'%>
20
7
 
21
8
  <table border="1">
22
9
  <tr>
@@ -38,20 +25,21 @@
38
25
  <% if total %>
39
26
  <% day_totals[day] += total %>
40
27
  <% week_totals[work_account] += total %>
41
- <td align="right" valign="top"><%='%.2f' % total%></td>
28
+ <td align="right" valign="top"><%='%d:%02d' % [total, 60 * total % 60]%></td>
42
29
  <% else %>
43
30
  <td/>
44
31
  <% end %>
45
32
  <% end %>
46
- <td align="right"><%=week_totals[work_account]%></td>
33
+ <td align="right"><%='%d:%02d' % [week_totals[work_account], 60 * week_totals[work_account] % 60]%></td>
47
34
  </tr>
48
35
  <% end %>
49
36
  <tr>
50
37
  <th><%=l :totals%></th>
51
38
  <% (0..6).each do |day| %>
52
- <th class="hours"><%='%.2f' % day_totals[day] if day_totals[day] > 0%></th>
39
+ <th class="hours"><%='%d:%02d' % [day_totals[day], 60 * day_totals[day] % 60] if day_totals[day] > 0%></th>
53
40
  <% end %>
54
- <th class="hours"><%= '%.2f' % week_totals.values.inject(0) {|total, work_account_total| total + work_account_total} %></th>
41
+ <% week_total = week_totals.values.inject(0) {|total, work_account_total| total + work_account_total} %>
42
+ <th class="hours"><%= '%d:%02d' % [week_total, 60 * week_total % 60] %></th>
55
43
  </tr>
56
44
  </table>
57
45
  </div>
data/lang/en.yaml CHANGED
@@ -21,6 +21,7 @@ customer: Customer
21
21
  daily_work_sheet: Daily work sheet
22
22
  delete: Delete
23
23
  description: Description
24
+ details: Details
24
25
  done: Done
25
26
  down: Down
26
27
  edit: Edit
@@ -46,6 +47,7 @@ invoice_code: Invoice Code
46
47
  invoice_short: Inv.
47
48
  left: Left
48
49
  listing_works: Recorded work
50
+ lock: Lock
49
51
  log_in: Log in
50
52
  log_out: Log out
51
53
  main_backlog: Main Backlog
@@ -88,6 +90,7 @@ select: Select
88
90
  shortcuts: Shortcuts
89
91
  signup: Sign Up
90
92
  specify: Specify
93
+ spreadsheet: Spreadsheet
91
94
  start: Start
92
95
  start_on: Start on
93
96
  start_work: Start
@@ -104,6 +107,7 @@ track_todo: Estimates
104
107
  track_done: Track work done
105
108
  track_times: Track start and stop times
106
109
  tuesday: Tuesday
110
+ unlock: Unlock
107
111
  unplanned_tasks: Unplanned tasks
108
112
  up: Up
109
113
  user: User
data/lang/no.yaml CHANGED
@@ -21,6 +21,7 @@ customer: Kunde
21
21
  daily_work_sheet: Timeføringsskjema
22
22
  delete: Slett
23
23
  description: Beskrivelse
24
+ details: Detaljer
24
25
  done: Utført
25
26
  down: Ned
26
27
  edit: Rediger
@@ -46,6 +47,7 @@ invoice_code: Faktureringskode
46
47
  invoice_short: Fakt
47
48
  left: Venstre
48
49
  listing_works: Registrert arbeid
50
+ lock: Lås
49
51
  log_in: Log inn
50
52
  log_out: Log ut
51
53
  main_backlog: Hovedliste
@@ -88,6 +90,7 @@ select: Velg
88
90
  shortcuts: Knapper
89
91
  signup: Innmelding
90
92
  specify: Spesifisèr
93
+ spreadsheet: Regneark
91
94
  start: Start
92
95
  start_on: Start på
93
96
  start_work: Start arbeid
@@ -103,6 +106,7 @@ track_todo: Estimater
103
106
  track_done: Spor utført arbeid
104
107
  track_times: Spor start- og stopptider
105
108
  tuesday: Tirsdag
109
+ unlock: Lås opp
106
110
  unplanned_tasks: Ikke planlagte oppgaver
107
111
  up: Opp
108
112
  user: Bruker
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Uwe Kubosch
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-02 00:00:00 +01:00
12
+ date: 2008-02-05 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -156,6 +156,7 @@ files:
156
156
  - app/views/works/_row_field.rhtml
157
157
  - app/views/works/_form.rhtml
158
158
  - app/views/works/weekly_work_sheet.rhtml
159
+ - app/views/works/_weekly_work_sheet_buttons.rhtml
159
160
  - app/views/works/show.rhtml
160
161
  - app/views/works/weekly_work_sheet_by_work_account.rhtml
161
162
  - app/views/layouts