backlog 0.17.5 → 0.17.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,19 @@
1
+ == 0.17.6 2008-01-17
2
+
3
+ === Features
4
+
5
+ * Allowed moving a task from one backlog to another.
6
+ * Added simple summary to work account view.
7
+
8
+ === Fixes
9
+
10
+ * Minor cosmetic adjustment of task list.
11
+ * Fixed application error when displaying completed tasks.
12
+ * Fixed error when trying to create new task with errors (duplicate description).
13
+ * Fixed showing of work record for earlier years.
14
+ * Made task description bold in task lists for better readability.
15
+ * Changed dependency to rmagick to 1.15.12 instead of newest since rmagick 2 requires very new ImageMagick.
16
+
1
17
  == 0.17.5 2008-01-15
2
18
 
3
19
  === Fixes
data/Rakefile CHANGED
@@ -32,7 +32,7 @@ Hoe.new("backlog", APP::VERSION) do |p|
32
32
  }
33
33
  p.need_zip = true
34
34
  p.url = 'http://rubyforge.org/projects/backlog/'
35
- p.extra_deps = [['rails', '>= 1.2.4'], ['gruff', '>= 0.2.9'], ['rmagick', '>= 1.15.12'], ['postgres', '>= 0.7.9']]
35
+ p.extra_deps = [['rails', '>= 1.2.4'], ['gruff', '>= 0.2.9'], ['rmagick', '= 1.15.12'], ['postgres', '>= 0.7.9']]
36
36
  p.rsync_args = "-av --delete --exclude=wiki*"
37
37
  end
38
38
 
@@ -171,7 +171,7 @@ class BacklogsController < ApplicationController
171
171
  task.save!
172
172
  end
173
173
  end
174
- render :text => 'Updated sort order'
174
+ render :text => 'alert("Updated sort order");'
175
175
  end
176
176
 
177
177
  private
@@ -196,15 +196,16 @@ class PeriodsController < ApplicationController
196
196
  end
197
197
 
198
198
  def order
199
- params.keys.find {|k| k =~ /active_tasks_(.*)/}
199
+ if params.keys.find {|k| k =~ /active_tasks_(.*)/}
200
200
  period_id = $1
201
- tasks = params["active_tasks_#{period_id}"].select {|id| not id.empty?}
201
+ ids = params["active_tasks_#{period_id}"]
202
+ tasks = ids.select {|id| not id.empty?}
202
203
  tasks.each_with_index do |id,idx|
203
204
  task = Task.find(id)
204
205
  task.insert_at(idx + 1)
205
206
  task.save!
206
207
  end
207
- render :text => 'Updated sort order'
208
+ end
208
209
  end
209
210
 
210
211
  private
@@ -44,12 +44,14 @@ class TasksController < ApplicationController
44
44
  populate_layout
45
45
  @backlogs = Backlog.find(:all, :order => 'name')
46
46
  @periods = Period.find_active_or_future
47
+ @customers = Customer.find(:all)
47
48
  render :action => 'new'
48
49
  end
49
50
  end
50
51
 
51
52
  def edit
52
53
  @task ||= Task.find(params[:id])
54
+ @task.backlog_id = params[:task][:backlog_id] if params[:task] && params[:task][:backlog_id]
53
55
  @task.period_id = params[:task][:period_id] if params[:task] && params[:task][:period_id]
54
56
  @periods = Period.find_active_or_future
55
57
  @backlogs = Backlog.find(:all, :order => 'name')
@@ -14,6 +14,11 @@ class WorkAccountsController < ApplicationController
14
14
 
15
15
  def show
16
16
  @work_account = WorkAccount.find(params[:id])
17
+ works = @work_account.works.select{|w|w.user_id == current_user.id}
18
+ @backlog_totals = works.to_summarized_hash {|work| [work.task && work.task.backlog, work.hours]}
19
+ @task_totals = works.to_summarized_hash {|work| [work.task, work.hours]}
20
+ @task_totals_per_backlog = @task_totals.to_a.to_grouped_hash {|task, hours| [task && task.backlog, [task, hours]]}
21
+ @total_hours = works.inject(BigDecimal('0')) {|total, work| total += work.hours}
17
22
  end
18
23
 
19
24
  def new
@@ -42,7 +42,7 @@ class WorksController < ApplicationController
42
42
  if backlog_name && backlog_name.size > 0 && task_description && task_description.size > 0
43
43
  backlog = Backlog.find_by_name(backlog_name)
44
44
  task = backlog.tasks_with_children.find{|t| t.description == task_description}
45
- params[:work][:task_id] = task.id
45
+ params[:work][:task_id] = task.id if task
46
46
  end
47
47
  account_name = params[:work].delete(:work_account_name)
48
48
  if account_name && account_name.size > 0
@@ -137,8 +137,9 @@ class WorksController < ApplicationController
137
137
  end
138
138
 
139
139
  def weekly_work_sheet
140
- @week = (params[:id] && params[:id].to_i) || Date.today.cweek
141
- @rows = Work.works_for_week(@week)
140
+ @year = (params[:year] && params[:year].to_i) || Date.today.year
141
+ @week = (params[:week] && params[:week].to_i) || Date.today.cweek
142
+ @rows = Work.works_for_week(@year, @week)
142
143
  render :layout => 'wide'
143
144
  end
144
145
 
@@ -1,5 +1,5 @@
1
1
  module WorksHelper
2
2
  def week_date(day)
3
- Date.commercial(Date.today.year, @week, day).strftime('%d/%m')
3
+ Date.commercial(@year, @week, day).strftime('%d/%m')
4
4
  end
5
5
  end
data/app/models/work.rb CHANGED
@@ -30,8 +30,8 @@ class Work < ActiveRecord::Base
30
30
  # [m2, t2, nil,t2, nil,nil, nil],
31
31
  # [nil,t2, nil,nil,nil,nil, nil],
32
32
  # ]
33
- def self.works_for_week(week_no, user = current_user)
34
- first = Date.commercial(Date.today.year, week_no, 1)
33
+ def self.works_for_week(year, week_no, user = current_user)
34
+ first = Date.commercial(year, week_no, 1)
35
35
  last = first + 7
36
36
  works = find(:all, :conditions => "completed_at IS NOT NULL AND started_at BETWEEN '#{first.to_time.iso8601}' AND '#{last.to_time.iso8601}'", :order => 'started_at')
37
37
  length = 0
@@ -98,6 +98,10 @@ class Work < ActiveRecord::Base
98
98
  end
99
99
 
100
100
  def completed_at_time=(new_value)
101
+ if new_value == ''
102
+ self.completed_at = nil
103
+ return
104
+ end
101
105
  raise "invalid time format: #{new_value}" unless new_value =~ /(\d{2}):(\d{2})/
102
106
  new_hour, new_minutes = $1, $2
103
107
  t = completed_at || Time.now
@@ -8,5 +8,9 @@ class WorkAccount < ActiveRecord::Base
8
8
  def enable_invoicing?
9
9
  invoice_code && invoice_code.length > 0
10
10
  end
11
+
12
+ def total_hours
13
+ works.inject(BigDecimal('0')) {|total, work| total + work.hours}
14
+ end
11
15
 
12
16
  end
@@ -22,7 +22,7 @@
22
22
  <% end %>
23
23
  </div>
24
24
  <%for list_id in list_ids %>
25
- <%=sortable_element list_id, :url => { :action => :order }, :containment => list_ids, :constraint => false %>
25
+ <%=sortable_element list_id, :url => { :action => :order }, :containment => list_ids, :constraint => false, :dropOnEmpty => true %>
26
26
  <% end %>
27
27
  <p id="no_tasks_message"<%=' style="display: none;"' if @tasks and not @tasks.empty? %>>
28
28
  <%=l :no_pending_tasks_in_backlog %>
@@ -0,0 +1 @@
1
+ record page, 'alert("hi");'
@@ -47,10 +47,10 @@ function echoRuby(ruby) {
47
47
  alert(Ruby.eval(ruby));
48
48
  }
49
49
 
50
- window.onload = function() {
51
- Ruby.init(function(result) {
52
- alert(result);
53
- });
54
- }
50
+ //window.onload = function() {
51
+ // Ruby.init(function(result) {
52
+ // alert(result);
53
+ // });
54
+ //}
55
55
 
56
56
  </script>
@@ -7,7 +7,7 @@
7
7
  <%=render :partial => '/tasks/fields_header', :locals => {:backlog => @backlog, :active => false, :track_times => false, :work_done => work_done} %>
8
8
  <ul id="completed_tasks_<%=period && period.id%>" class="task_list" style="width: 100%;">
9
9
  <% @completed_tasks.select {|t| t.period == period}.each do |task| %>
10
- <%=render :partial => '/tasks/task', :locals => { :task => task, :i => i, :active => false, :highlight_task => task == @selected_task, :hidden => false } %>
10
+ <%=render :partial => '/tasks/task', :locals => { :task => task, :i => i, :active => false, :highlight_task => task == @selected_task, :hidden => false, :show_backlog => controller.class != BacklogsController } %>
11
11
  <% i += 1 %>
12
12
  <% end %>
13
13
  </ul>
@@ -1,6 +1,6 @@
1
1
  <!--[form:task]-->
2
2
  <p>
3
- <% if @task.backlog.nil? || @task.new_record? %>
3
+ <% if @task.backlog.nil? || @task.new_record? || @task.active? %>
4
4
  <label for="task_backlog_id"><%=l :backlog%></label><br/>
5
5
  <%= select 'task', 'backlog_id', [['', '']] + @backlogs.map{|backlog| [backlog.name, backlog.id]}, {}, :onchange => "form.action = '#{url_for}'; form.submit();" %>
6
6
  <% else %>
@@ -16,9 +16,13 @@
16
16
 
17
17
  <% if @task.backlog && @task.backlog.enable_periods? %>
18
18
  <p><label for="task_period_id"><%=l :period%></label><br/>
19
+ <% if @task.active? %>
19
20
  <%= select 'task', 'period_id', [['', '']] + @periods.map{|p| [p.name, p.id]}, {},
20
21
  :onchange => remote_function(:update => 'period_link',
21
22
  :url => { :controller => 'periods', :action => 'make_link', :id => "'+value+'", :escape => false }) %>
23
+ <% else %>
24
+ <%=detour_to @task.period, :controller => 'periods', :action => :show, :id => @task.period %>
25
+ <% end %>
22
26
  <span id="period_link">
23
27
  <%=render :partial => '/periods/link', :locals => {:period => @task.period}%>
24
28
  </span>
@@ -33,13 +37,15 @@
33
37
  <% if @task.active? -%>
34
38
  <%=text_field 'task', 'description', :size => 64, :maxlength => 80 %>
35
39
  <% else -%>
36
- <%=@task.description -%>
40
+ <b><%=@task.description -%></b>
37
41
  <% end -%>
38
42
  </p>
39
43
 
40
- <% if @task.enable_customer? %>
44
+ <% if @task.enable_customer? && (@task.active? || @task.customer) %>
41
45
  <p><label for="task_customer"><%=l :customer%></label><br/>
46
+ <% if @task.active? %>
42
47
  <%=select 'task', 'customer_id', [['', '']] + @customers.map{|c| [c.name, c.id]} %>
48
+ <% end %>
43
49
  <% if @task.customer %>
44
50
  <%=image_detour_to('customer.png', "#{l(:customer)} #{@task.customer.name}", {:controller => 'customers', :action => :edit, :id => @task.customer}, {:class => 'image-submit', :style => 'vertical-align: bottom'}) %>
45
51
  <% end %>
@@ -53,8 +59,10 @@
53
59
  <%= text_field 'task', 'initial_estimate', :size => 4 %>
54
60
  </p>
55
61
  <% else %>
56
- <p style="float: left"><label for="estimate_todo"><%=l :estimate%></label><br/>
62
+ <% if @task.active? %>
63
+ <p style="float: left; margin-right: 1em"><label for="estimate_todo"><%=l :estimate%></label><br/>
57
64
  <%=text_field 'estimate', 'todo', :size => 4, :value => @task.todo %>
65
+ <% end %>
58
66
  </p>
59
67
  <% end %>
60
68
  <% end %>
@@ -16,7 +16,7 @@
16
16
  <%=detour_to "##{@task.id}", :controller => 'tasks', :action => :edit, :id => @task.id, :style => 'border: 0px; margin: 0px; padding: 0px' if @task.position || @task.depth == 0 %>
17
17
  </div>
18
18
  <div id="task_<%=@task.id%>_description" class="task_description">
19
- <%=h(@task.description) %>
19
+ <b><%=h(@task.description)%></b>
20
20
  <% if show_backlog %>
21
21
  <br/>
22
22
  <%=l :backlog%>: <%=detour_to(h(@task.backlog.name), :controller => 'backlogs', :action => :show, :id => @task.backlog) %>
@@ -36,7 +36,7 @@ function handleEvent(field, event, id) {
36
36
  </script>
37
37
 
38
38
  <% if @tasks %>
39
- <%=render :partial => '/tasks/fields_header', :locals => {:backlog => nil, :active => true, :track_times => @tasks.find {|t|t.period && t.period.active?}} %>
39
+ <%=render :partial => '/tasks/fields_header', :locals => {:backlog => nil, :active => true, :track_todo => @tasks.find {|t|t.track_todo?}, :track_done => @tasks.find {|t|t.track_done?}, :track_times => @tasks.find {|t|t.period && t.period.active?}} %>
40
40
  <ul class="task_list">
41
41
  <% i = 0 %>
42
42
  <% current_backlog = nil %>
@@ -1,8 +1,33 @@
1
- <% for column in WorkAccount.content_columns %>
2
- <p>
3
- <b><%= column.human_name %>:</b> <%=h @work_account.send(column.name) %>
4
- </p>
5
- <% end %>
1
+ <% @page_title = "#{l(:work_account)} #{l(:work_account)}" %>
6
2
 
7
- <%= link_to 'Edit', :action => 'edit', :id => @work_account %> |
8
- <%= link_to 'Back', :action => 'list' %>
3
+ <div id="spotlight">
4
+ <div class="btitle">
5
+ <h4><%=@work_account.name%></h4>
6
+ </div>
7
+
8
+ <table>
9
+ <% for backlog in @backlog_totals.keys %>
10
+ <tr>
11
+ <th><%=backlog ? backlog.name : l(:no_backlog)%></th>
12
+ <th><%=@backlog_totals[backlog]%></th>
13
+ </tr>
14
+ <% for task, hours in @task_totals_per_backlog[backlog] %>
15
+ <tr>
16
+ <td>
17
+ <% if task %>
18
+ <%=link_to task.description, :controller => 'tasks', :action => :edit, :id => task.id %>
19
+ <% end %>
20
+ </td>
21
+ <td align="right" valign="top"><%='%.2f' % hours%></td>
22
+ </tr>
23
+ <% end %>
24
+ <% end %>
25
+ <tr>
26
+ <th>Total hours</th>
27
+ <th><%=@total_hours%></th>
28
+ </tr>
29
+ </table>
30
+
31
+ <%= link_to 'Edit', :action => 'edit', :id => @work_account %> |
32
+ <%= link_to 'Back', :action => 'list' %>
33
+ </div>
@@ -18,6 +18,7 @@
18
18
  <%=render :partial => 'row_field', :locals => {:field => 'started_at_time'} %>
19
19
  </td>
20
20
  <td align="right">
21
+ <%=render :partial => 'row_field', :locals => {:field => 'completed_at_time'} %>
21
22
  </td>
22
23
  <td align="right">
23
24
  <% remote_form_for :work, :url => {:action => :update_row, :id => @work.id} do |f|%>
@@ -5,8 +5,8 @@
5
5
  <% invoicing = @rows.find {|r| r.find {|w| w && w.work_account.enable_invoicing?}} %>
6
6
  <% columns = 2 + (track_times ? 2 : 0) + (invoicing ? 1 : 0) %>
7
7
 
8
- <div style="float: left"><%=link_to(image_tag('arrow_left.png'), :id => (@week - 1))%></div>
9
- <div style="float: right"><%=link_to(image_tag('arrow_right.png'), :id => (@week + 1))%></div>
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
10
 
11
11
  <h1>Work for week <%=@week%><%=user? ? " for #{user.login}" : ''%></h1>
12
12
 
data/config/routes.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  ActionController::Routing::Routes.draw do |map|
2
2
  map.connect '', :controller => "welcome"
3
+ map.connect ':controller/:action/:year/:week'
3
4
  map.connect ':controller/:action/:id.:format'
4
5
  map.connect ':controller/:action/:id'
5
6
  end
data/lib/array_helper.rb CHANGED
@@ -6,5 +6,37 @@ class Array
6
6
  end
7
7
  calculated_value
8
8
  end
9
+
10
+ def to_freq_hash
11
+ freq = {}
12
+ each do |e|
13
+ freq[e] = freq[e].to_i + 1
14
+ end
15
+ freq
16
+ end
17
+
18
+ def to_summarized_hash(operation_symbol = :+)
19
+ sums = {}
20
+ each do |e|
21
+ key, value = yield(e)
22
+ if sums[key]
23
+ sums[key] = sums[key].send(operation_symbol, value)
24
+ else
25
+ sums[key] = value
26
+ end
27
+ end
28
+ sums
29
+ end
30
+
31
+ def to_grouped_hash
32
+ groups = {}
33
+ each do |e|
34
+ key, value = yield(e)
35
+ groups[key] ||= []
36
+ groups[key] << value
37
+ end
38
+ groups
39
+ end
40
+
9
41
  end
10
42
 
@@ -16,7 +16,7 @@ table.input td {vertical-align: top; margin: 0; border: 0; padding: 0 1px;}
16
16
  .task_list {width: 100%; text-align: left; list-style-type: none; padding-left: 0}
17
17
  .task_list li {margin-left: 0}
18
18
  .tasks {cursor: move}
19
- .task_id {float: left; padding-left: 2px; width: 3em; text-align: center}
19
+ .task_id {float: left; padding-left: 2px; width: 3.5em; text-align: center}
20
20
  .task_description {float: left; padding: 1px; width: auto}
21
21
  .task_start {float: left; width: 5em; text-align: center}
22
22
  .task_end_work {float: left; width: 2em}
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.17.5
4
+ version: 0.17.6
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-01-15 00:00:00 +01:00
12
+ date: 2008-01-19 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -35,7 +35,7 @@ dependencies:
35
35
  version_requirement:
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.15.12
41
41
  version:
@@ -81,6 +81,7 @@ files:
81
81
  - app/views/periods/move_task_to_period.rjs
82
82
  - app/views/periods/edit.rhtml
83
83
  - app/views/periods/_form.rhtml
84
+ - app/views/periods/order.rjs
84
85
  - app/views/periods/show.rhtml
85
86
  - app/views/welcome
86
87
  - app/views/redirect.rjs