backlog 0.2.1 → 0.3.0

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,8 @@
1
+ == 0.3.0 2007-08-02
2
+
3
+ * Improved workflow
4
+ * Added task list to backlog edit view
5
+
1
6
  == 0.2.1 2007-07-31
2
7
 
3
8
  * Improved workflow
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ require 'tasks/rails'
11
11
 
12
12
  require 'hoe'
13
13
 
14
- Hoe.new("backlog", '0.2.1') do |p|
14
+ Hoe.new("backlog", '0.3.0') do |p|
15
15
  p.rubyforge_name = "backlog"
16
16
  p.summary = "Application to aid collecting, processing, organizing, reviewing and doing tasks."
17
17
  p.description = p.paragraphs_of('README.txt', 0..-1).join("\n\n")
@@ -67,6 +67,10 @@ class ApplicationController < ActionController::Base
67
67
  end
68
68
 
69
69
  def store_detour(options)
70
+ if session[:detours] && session[:detours].last == options
71
+ puts "duplicate detour: #{options}"; STDOUT.flush
72
+ return
73
+ end
70
74
  puts "adding detour: #{options}"; STDOUT.flush
71
75
  session[:detours] ||= []
72
76
  session[:detours] << options
@@ -118,8 +122,8 @@ class ApplicationController < ActionController::Base
118
122
  end
119
123
 
120
124
  def populate_layout
121
- @period = Period.find(:first, params[:id]) if params[:id]
122
- @owner = @period.party if @period
125
+ # @period = Period.find(:first, params[:id]) if params[:id]
126
+ # @owner = @period.party if @period
123
127
  populate_shortcuts
124
128
 
125
129
  # TODO (uwe): This does not scale!
@@ -48,6 +48,10 @@ class BacklogsController < ApplicationController
48
48
 
49
49
  def edit
50
50
  @backlog = Backlog.find(params[:id])
51
+ @tasks = @backlog.tasks.sort do |t1, t2|
52
+ (t1.position && (t2.position ? t1.position <=> t2.position : -1)) ||
53
+ (t2.position ? 1 : t1.finished_at <=> t2.finished_at)
54
+ end
51
55
  end
52
56
 
53
57
  def update
@@ -31,6 +31,8 @@ class TasksController < ApplicationController
31
31
  redirect_to :controller => 'periods', :action => 'show', :id => @task.period, :task => @task.id
32
32
  else
33
33
  populate_layout
34
+ @backlogs = Backlog.find(:all, :order => 'name')
35
+ @periods = Period.find_active_or_future
34
36
  render :action => 'new'
35
37
  end
36
38
  end
@@ -122,7 +124,7 @@ class TasksController < ApplicationController
122
124
  period = params[:period_id] && Period.find(params[:period_id])
123
125
  if period && period.active_or_future?
124
126
  next_task = task.higher_item ? task.higher_item : task.lower_item ? task.lower_item : task
125
- task.move_to_period period, user
127
+ task.move_to_period period
126
128
  if with_layout
127
129
  back_or_redirect_to :controller => 'periods', :action => :show, :id => next_task.period, :task_id => next_task.id
128
130
  else
@@ -151,13 +153,13 @@ class TasksController < ApplicationController
151
153
  def abort
152
154
  task = Task.find params[:id]
153
155
  task.abort(user)
154
- redirect_to(:controller => "periods", :action => "show", :id => task.period)
156
+ back_or_redirect_to(:controller => "periods", :action => "show", :id => task.period)
155
157
  end
156
158
 
157
159
  def reopen
158
160
  task = Task.find(params[:id])
159
161
  task.reopen(user)
160
- redirect_to :controller => 'periods', :action => :show, :id => task.period, :task => task.id
162
+ back_or_redirect_to :controller => 'periods', :action => :show, :id => task.period, :task => task.id
161
163
  end
162
164
 
163
165
  def start_work
@@ -12,20 +12,19 @@ module ApplicationHelper
12
12
  end
13
13
 
14
14
  def detour_to(title, options, html_options = nil)
15
- #link_to title, options.update({:detour => {:controller => @controller.controller_name, :action => @controller.action_name, :id => params[:id]}}), html_options
16
15
  link_to title, options.update({:detour => params.reject {|k, v| [:detour, :return_from_detour].include? k.to_sym}}), html_options
17
16
  end
18
17
 
19
- def image_detour_to(image_source, title, image_options, options )
18
+ def image_detour_to(image_source, title, url_options, image_options = nil, post = false)
20
19
  image_options ||= {:class => 'image-submit'}
21
20
  image_options.update :alt => title, :title => title
22
- detour_to image_tag(image_source, image_options), options
21
+ detour_to image_tag(image_source, image_options), url_options, :method => post ? :post : :get
23
22
  end
24
23
 
25
24
  def back_or_link_to(title, options)
26
25
  if session[:detours]
27
- options = session[:detours].last.update({:return_from_detour => true})
28
- puts "linked detour: #{options}"
26
+ options = {:return_from_detour => true}.update(session[:detours].last)
27
+ puts "linked return from detour: #{options}"
29
28
  end
30
29
  link_to title, options
31
30
  end
data/app/models/party.rb CHANGED
@@ -9,4 +9,8 @@ class Party < ActiveRecord::Base
9
9
  self.class.name.downcase.pluralize
10
10
  end
11
11
 
12
+ def icon
13
+ to_sym.to_s + '.png'
14
+ end
15
+
12
16
  end
data/app/models/task.rb CHANGED
@@ -17,6 +17,9 @@ class Task < ActiveRecord::Base
17
17
  validates_size_of :customer, :maximum => 64, :if => :customer
18
18
  validates_presence_of :backlog_id, :if => Proc.new { |task| task.parent_id.nil? }
19
19
  validates_presence_of :parent_id, :if => Proc.new { |task| task.backlog_id.nil? }
20
+ #validates_absence_of :position, :if => :finished_at
21
+ #validates_absence_of :finished_at, :if => :position
22
+ validates_presence_of :resolution, :if => :finished_at
20
23
  validates_uniqueness_of :description, :scope => :period_id
21
24
  validates_uniqueness_of :position, :scope => :period_id, :allow_nil => true
22
25
 
@@ -24,7 +27,7 @@ class Task < ActiveRecord::Base
24
27
  unless (self.period_id || self.parent_id) && !(self.period_id && self.parent_id)
25
28
  errors.add :parent_id, "A task may have either period or parent task set, not both."
26
29
  end
27
- if new_record? && self.period.passed?
30
+ if new_record? && self.period && self.period.passed?
28
31
  errors.add :period_id, "You may not add a task to a past period."
29
32
  end
30
33
  end
@@ -49,7 +52,7 @@ class Task < ActiveRecord::Base
49
52
  estimates.last ? estimates.last.todo : initial_estimate
50
53
  end
51
54
 
52
- def estimate(new_todo, user)
55
+ def estimate(new_todo)
53
56
  return unless new_todo && new_todo != ''
54
57
  previous_estimate = estimates.last
55
58
  new_estimate = Estimate.new
@@ -61,13 +64,13 @@ class Task < ActiveRecord::Base
61
64
  now = Time.now
62
65
  if previous_estimate && (now < previous_estimate.created_at || now.strftime('%Y-%m-%DT%H:%M:%S') == previous_estimate.created_at.strftime('%Y-%m-%DT%H:%M:%S'))
63
66
  previous_estimate.todo = new_todo
64
- previous_estimate.user = user
67
+ previous_estimate.user = current_user
65
68
  previous_estimate.save!
66
69
  else
67
70
  new_estimate.task_id = self.id
68
71
  new_estimate.todo = new_todo
69
72
  new_estimate.created_at = now
70
- new_estimate.user = user
73
+ new_estimate.user = current_user
71
74
  new_estimate.save!
72
75
  estimates << new_estimate
73
76
  end
@@ -94,13 +97,13 @@ class Task < ActiveRecord::Base
94
97
  total
95
98
  end
96
99
 
97
- def open(user)
100
+ def open
98
101
  if finished_at
99
102
  self.finished_at = nil
100
103
  self.resolution = nil
101
- estimate(initial_estimate, user)
104
+ estimate(initial_estimate)
102
105
  insert_at 1
103
- parent.open(user) if parent
106
+ parent.open if parent
104
107
  end
105
108
  end
106
109
 
@@ -114,7 +117,7 @@ class Task < ActiveRecord::Base
114
117
  end
115
118
  end
116
119
 
117
- def move_to_period(period, user)
120
+ def move_to_period(period)
118
121
  raise "Period missing" unless period
119
122
  raise "Cannot move finished tasks" unless active?
120
123
 
@@ -122,26 +125,26 @@ class Task < ActiveRecord::Base
122
125
  new_task = Task.find_by_period_id_and_id(period.id, ancestor_id)
123
126
  new_task ||= Task.find_by_period_id_and_previous_task_id(period.id, ancestor_id)
124
127
  new_task ||= Task.new
125
- new_task.open(user)
128
+ new_task.open
126
129
  new_task.previous_task_id = self.previous_task_id || self.id
127
- new_task.backlog = backlog
130
+ new_task.backlog = root_task.backlog
128
131
  new_task.period = period
129
132
  new_task.description = self.description
130
133
  new_task.save!
131
- new_task.estimate(self.todo, user)
134
+ new_task.estimate(self.todo)
132
135
  new_task.move_to_top
133
- new_task.estimate(self.todo, user)
134
- self.finish(new_task.period.party == self.period.party ? Task::POSTPONED : Task::MOVED, true, user)
136
+ new_task.estimate(self.todo)
137
+ self.finish(new_task.period.party == self.period.party ? Task::POSTPONED : Task::MOVED, true, current_user)
135
138
  end
136
139
 
137
140
  def finish(resolution, save_work, user)
138
141
  unless finished_at || work_started?
139
- remove_from_list
140
142
  self.finished_at = Time.now
141
143
  self.resolution = resolution
142
144
  self.position = nil
143
145
  save!
144
- estimate(0, user) if save_work
146
+ remove_from_list
147
+ estimate(0) if save_work
145
148
  parent.check_finished(self.finished_at, resolution, save_work, user) if parent
146
149
  end
147
150
  end
@@ -7,3 +7,20 @@
7
7
  <%= back_or_link_to l(:back), :action => 'show', :id => @backlog %>
8
8
  <% end %>
9
9
  </div>
10
+
11
+ <div id="maincontent">
12
+ <div class="mainblock">
13
+ <div class="btitle">
14
+ <h4><%=l :tasks%></h4>
15
+ </div>
16
+
17
+ <table>
18
+ <%= render :partial => '/tasks/backlog_header', :locals => {:backlog => @backlog} %>
19
+ <% i = 0 %>
20
+ <% for @task in @tasks %>
21
+ <%= render :partial => '/tasks/task/', :locals => {:task => @task, :i => i += 1, :active => true, :highlight => false} %>
22
+ <% end %>
23
+ </table>
24
+ </div>
25
+
26
+ </div>
@@ -10,7 +10,7 @@
10
10
  <%= hidden_field 'period', 'party_id' %><%=detour_to h(@period.party.name), :controller => @period.party.type.name.downcase.pluralize, :action => :edit, :id => @period.party%>
11
11
  <% end %>
12
12
  <% if @period.party %>
13
- <%=image_detour_to(@period.party.to_sym.to_s + '.png', "#{l(@period.party.to_sym)} #{@period.party.name}", nil, :controller => @period.party.to_s, :action => :edit, :id => @period.party) %>
13
+ <%=image_detour_to(@period.party.icon, "#{l(@period.party.to_sym)} #{@period.party.name}", :controller => @period.party.controller, :action => :edit, :id => @period.party) %>
14
14
  <% end %>
15
15
  </p>
16
16
 
@@ -4,7 +4,7 @@
4
4
  <% form_tag :action => 'update', :id => @period do %>
5
5
  <%= render :partial => 'form' %>
6
6
  <%= submit_tag l(:save) %>
7
+ <%= link_to l(:back), :action => 'show', :id => @period %>
7
8
  <% end %>
8
9
 
9
- <%= link_to l(:back), :action => 'show', :id => @period %>
10
10
  </div>
@@ -2,12 +2,11 @@
2
2
 
3
3
  <tr valign="top">
4
4
  <td>
5
- <%= image_detour_to('add.png', l(:new_task), nil, :controller => 'tasks', :action => :new, :task => {:backlog_id => @backlog.id, :period_id => @period.id})%>
5
+ <%= image_detour_to('add.png', l(:new_task), :controller => 'tasks', :action => :new, :task => {:backlog_id => @backlog.id, :period_id => @period && @period.id})%>
6
6
  </td>
7
- <td colspan="4" valign="top">
7
+ <td colspan="4" style="vertical-align: middle">
8
8
  <h5>
9
- <%=h backlog.name %>
10
- <%=image_detour_to("clipboard.png", l(:backlog), nil, :controller => 'backlogs', :action => :edit, :id => @backlog) %>
9
+ <%=detour_to(h(backlog.name), :controller => 'backlogs', :action => :edit, :id => @backlog) %>
11
10
  </h5>
12
11
  </td>
13
12
  <td width="*"/>
@@ -16,9 +15,7 @@
16
15
  <th/>
17
16
  <th align="center">#</th>
18
17
  <th><%=l :task %></th>
19
- <th><%=l :start if @period.track_times? && @period.active? %></th>
20
- <% if @period.track_work? -%>
21
- <th><%=l :done %></th>
22
- <% end %>
18
+ <th><%=l :start if @backlog.track_times? && @tasks.find {|t|t.period && t.period.active?} %></th>
19
+ <th><%=l :done if @backlog.track_done? %></th>
23
20
  <th width="*"><% l :todo if @backlog.track_todo? %></th>
24
21
  </tr>
@@ -10,7 +10,7 @@
10
10
  <%= hidden_field 'task', 'backlog_id' %><%=h @task.backlog.name%>
11
11
  <% end %>
12
12
  <% if @task.backlog %>
13
- <%=image_detour_to('clipboard.png', "#{l(:backlog)} #{@task.backlog.name}", {:class => 'image-submit', :style => 'vertical-align: bottom'}, :controller => 'backlogs', :action => :edit, :id => @task.backlog) %>
13
+ <%=image_detour_to('clipboard.png', "#{l(:backlog)} #{@task.backlog.name}", {:controller => 'backlogs', :action => :edit, :id => @task.backlog}, {:class => 'image-submit', :style => 'vertical-align: bottom'}) %>
14
14
  <% end %>
15
15
  </p>
16
16
 
@@ -18,7 +18,7 @@
18
18
  <p><label for="task_period_id"><%=l :period%></label><br/>
19
19
  <%= select 'task', 'period_id', [['', '']] + @periods.map{|p| [p.name, p.id]}, {}, :onchange => "form.action = '#{url_for}'; form.submit();" %>
20
20
  <% if @task.period %>
21
- <%=image_detour_to(@task.period.party.to_sym.to_s + '.png', "#{l(@task.period.party.to_sym)} #{@task.period.party.name}", nil, :controller => @task.period.party.to_s, :action => :edit, :id => @task.period.party) %>
21
+ <%=image_detour_to('period.png', "#{l :period} #{@task.period.name}", :controller => 'periods', :action => :edit, :id => @task.period) %>
22
22
  <% end %>
23
23
  <%=detour_to l(:new_period), :controller => 'periods', :action => :new %>
24
24
  </p>
@@ -8,7 +8,7 @@
8
8
  <% end %>
9
9
  </td>
10
10
  <td align="left" valign="top" width="1" nowrap="true">
11
- <%= @task.position if @task.depth == 0 %>
11
+ <%=detour_to @task.position.to_s, :controller => 'tasks', :action => :edit, :id => @task.id if @task.depth == 0 %>
12
12
  <%= ("&nbsp;" * @task.depth * 4) if @task.depth > 0 %>
13
13
  <%= l(@task.resolution.downcase) if @task.finished_at %>
14
14
  <%= "-" if @task.children.size > 0 %>
@@ -72,12 +72,12 @@
72
72
  <% if @task.active? %>
73
73
  <% if @task.loggable? %>
74
74
  <% unless @task.work_started? %>
75
- <%= image_button_to('arrow_right.png', l(:move_to_next_period), :controller => 'tasks', :action => :move_to_next_period, :id => @task)%>
76
- <%= image_button_to('ernes_stop.png', l(:abort), :controller => 'tasks', :action => :abort, :id => @task)%>
75
+ <%= image_detour_to('arrow_right.png', l(:move_to_next_period), {:controller => 'tasks', :action => :move_to_next_period, :id => @task}, nil, true)%>
76
+ <%= image_detour_to('ernes_stop.png', l(:abort), {:controller => 'tasks', :action => :abort, :id => @task}, nil, true)%>
77
77
  <% end %>
78
78
  <% end %>
79
79
  <% elsif not @task.period.passed? && @task.leaf? %>
80
- <%=image_button_to('/images/eraser.png', l(:reopen), :controller => 'tasks', :action => :reopen, :id => @task) %>
80
+ <%=image_detour_to('/images/eraser.png', l(:reopen), {:controller => 'tasks', :action => :reopen, :id => @task}, nil, true) %>
81
81
  <% end -%>
82
82
  <% end -%>
83
83
  </td>
@@ -1,7 +1,5 @@
1
1
  <div id="spotlight">
2
- <h1>Editing task</h1>
3
-
4
- <%=h @task.inspect%>
2
+ <% @page_title = "#{l :editing} #{l :task}" %>
5
3
 
6
4
  <% form_tag :action => 'update', :id => @task do %>
7
5
  <%= render :partial => 'form' %>
@@ -1,3 +1,3 @@
1
- <%=image_detour_to('hammer.png', l(:weekly_work_sheet), nil, :controller => 'works', :action => :weekly_work_sheet)%>
1
+ <%=image_detour_to('hammer.png', l(:weekly_work_sheet), :controller => 'works', :action => :weekly_work_sheet)%>
2
2
  <%=link_to(image_tag(url_for("hammer.png"), :alt => l(:daily_work_sheet), :title => l(:daily_work_sheet), :class => 'image-submit'), :controller => 'works', :action => :daily_work_sheet)%>
3
3
  <%=link_to(image_tag(url_for("hammer.png"), :alt => l(:edit_works), :title => l(:edit_works), :class => 'image-submit'), :controller => 'periods', :action => 'list_work', :id => (@period ? @period.id : (@backlog && @backlog.periods.first ? @backlog.periods.first.id : nil)))%>
@@ -20,7 +20,7 @@
20
20
  <% day_total += @work.hours if @work %>
21
21
  <tr>
22
22
  <td>
23
- <%=image_detour_to('period.png', l(:period), nil, :controller => 'periods', :action => :show, :id => @work.task.period) %>
23
+ <%=image_detour_to('period.png', l(:period), :controller => 'periods', :action => :show, :id => @work.task.period) %>
24
24
  </td>
25
25
  <td>
26
26
  <form>
data/lang/en.yaml CHANGED
@@ -72,6 +72,7 @@ started_at: Started at
72
72
  started_tasks: Started tasks
73
73
  sunday: Sunday
74
74
  task: Task
75
+ tasks: Tasks
75
76
  thursday: Thursday
76
77
  todo: Todo
77
78
  totals: Totals
data/lang/no.yaml CHANGED
@@ -71,6 +71,7 @@ start_work: Start arbeid
71
71
  started_at: Start tid
72
72
  sunday: Søndag
73
73
  task: Oppgave
74
+ tasks: Oppgaver
74
75
  thursday: Torsdag
75
76
  todo: Igjen
76
77
  totals: Totalt
@@ -5,10 +5,12 @@ first:
5
5
  backlog_id: 1
6
6
  period_id: 1
7
7
  description: first task
8
+ position: 1
8
9
  another:
9
10
  id: 2
10
11
  created_at: 2007-06-12
11
12
  backlog_id: 1
12
13
  period_id: 2
13
14
  description: second task
15
+ position: 2
14
16
 
@@ -56,6 +56,9 @@ class TasksControllerTest < Test::Unit::TestCase
56
56
 
57
57
  post :create, :task => {:description => 'an important task', :backlog_id => '2', :period_id => '2'}
58
58
 
59
+ task = assigns(:task)
60
+ assert_equal [], task.errors.full_messages
61
+
59
62
  assert_response :redirect
60
63
  assert_redirected_to :controller => 'periods', :action => 'show', :id => Period.find(2)
61
64
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: backlog
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.1
7
- date: 2007-07-31 00:00:00 +02:00
6
+ version: 0.3.0
7
+ date: 2007-08-02 00:00:00 +02:00
8
8
  summary: Application to aid collecting, processing, organizing, reviewing and doing tasks.
9
9
  require_paths:
10
10
  - lib
@@ -226,6 +226,7 @@ files:
226
226
  - config/environments/datek_production.rb
227
227
  - LICENSE_LOCALIZATION
228
228
  - README.txt
229
+ - doc
229
230
  - Manifest.txt
230
231
  - vendor
231
232
  - vendor/plugins