backlog 0.21.1 → 0.21.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +19 -0
- data/app/controllers/application.rb +23 -5
- data/app/controllers/application.rb~ +207 -0
- data/app/controllers/periods_controller.rb +7 -3
- data/app/models/task.rb +4 -6
- data/app/models/user.rb +1 -0
- data/app/models/work_lock_nagger.rb +7 -5
- data/bin/backlog +14 -6
- data/etc/backlog.conf +9 -1
- data/test/functional/periods_controller_test.rb +54 -23
- metadata +4 -3
data/History.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
== 0.21.2 2008-02-08
|
2
|
+
|
3
|
+
=== Features
|
4
|
+
|
5
|
+
* Added ability to override the public application URL in the backlog.conf config file.
|
6
|
+
|
7
|
+
=== Fixes
|
8
|
+
|
9
|
+
* Changed so that End Work -> Start Work operations don't generate overlapping work records by default.
|
10
|
+
* Added checking of return code to the 'setup_unix' task so the script fails unless it can successfully
|
11
|
+
change to the postgresql administration user.
|
12
|
+
* Added "debug" and "bsd" options to administration script.
|
13
|
+
The "debug" option turns on tracing in the rake scripts.
|
14
|
+
The "bsd" option changes the postgresql admin user from "postgres" to "pgsql".
|
15
|
+
* Fixed bug 16427: http://rubyforge.org/tracker/index.php?func=detail&aid=16427&group_id=3829&atid=14750
|
16
|
+
When postponing the first task to a new sprint, the sprint is created and the task is postponed directly.
|
17
|
+
A white screen is displayed during the dialog, but it was the best solution I could find.
|
18
|
+
* Fixed the default host/port for Work Lock Nag email from localhost:3000 to read from the local network settings and backlog.conf.
|
19
|
+
|
1
20
|
== 0.21.1 2008-02-04
|
2
21
|
|
3
22
|
=== Features
|
@@ -71,7 +71,7 @@ class ApplicationController < ActionController::Base
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def rjs_detour_to(options)
|
74
|
-
store_detour(params)
|
74
|
+
store_detour(params, request.post?)
|
75
75
|
rjs_redirect_to(options)
|
76
76
|
end
|
77
77
|
|
@@ -80,7 +80,8 @@ class ApplicationController < ActionController::Base
|
|
80
80
|
render :template => 'redirect', :layout => false
|
81
81
|
end
|
82
82
|
|
83
|
-
def store_detour(options)
|
83
|
+
def store_detour(options, post = false)
|
84
|
+
options[:request_method] = :post if post
|
84
85
|
if session[:detours] && session[:detours].last == options
|
85
86
|
logger.debug "duplicate detour: #{options}"
|
86
87
|
return
|
@@ -102,7 +103,12 @@ class ApplicationController < ActionController::Base
|
|
102
103
|
def back_or_redirect_to(options)
|
103
104
|
if session[:detours]
|
104
105
|
detour = pop_detour
|
105
|
-
|
106
|
+
post = detour.delete(:request_method) == :post
|
107
|
+
if post
|
108
|
+
redirect_to_post(detour)
|
109
|
+
else
|
110
|
+
redirect_to detour
|
111
|
+
end
|
106
112
|
else
|
107
113
|
redirect_to options
|
108
114
|
end
|
@@ -143,7 +149,7 @@ class ApplicationController < ActionController::Base
|
|
143
149
|
# TODO (uwe): This does not scale!
|
144
150
|
#periods = Period.find(:all).select {|period| period.active_or_future?(true) && period.party.includes?(user)}
|
145
151
|
periods = Period.find_active_or_future(true)
|
146
|
-
|
152
|
+
|
147
153
|
|
148
154
|
@sidebars = periods.sort_by {|p| p.required_speed}.reverse.map do |period|
|
149
155
|
content = '<ul>'
|
@@ -186,4 +192,16 @@ class ApplicationController < ActionController::Base
|
|
186
192
|
User.find_by_id(user_id) if user_id
|
187
193
|
end
|
188
194
|
|
189
|
-
|
195
|
+
def redirect_to_post(options)
|
196
|
+
url = url_for options
|
197
|
+
render :text => <<EOF, :layout => false
|
198
|
+
<html>
|
199
|
+
<body onload="document.getElementById('form').submit()">
|
200
|
+
<form id="form" action="#{url}" method="POST">
|
201
|
+
</form>
|
202
|
+
</body>
|
203
|
+
</html>
|
204
|
+
EOF
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
class ApplicationController < ActionController::Base
|
2
|
+
include Localization
|
3
|
+
include UserSystem
|
4
|
+
include ApplicationHelper
|
5
|
+
include ActionView::Helpers::TagHelper
|
6
|
+
include ActionView::Helpers::JavaScriptHelper
|
7
|
+
include ActionView::Helpers::PrototypeHelper
|
8
|
+
include ActionView::Helpers::ScriptaculousHelper
|
9
|
+
include UrlForFix
|
10
|
+
|
11
|
+
layout :determine_layout
|
12
|
+
helper :user
|
13
|
+
before_filter :store_detour_from_params
|
14
|
+
before_filter :authenticate_user
|
15
|
+
before_filter :populate_layout
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@application_title = l :backlog
|
19
|
+
@application_description = l :backlog_description
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.in_place_edit_for(object, attribute, options = {})
|
23
|
+
define_method("set_#{object}_#{attribute}") do
|
24
|
+
@item = object.to_s.camelize.constantize.find(params[:id])
|
25
|
+
@item.update_attribute(attribute, params[:value])
|
26
|
+
render :text => @item.send(attribute).to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def determine_layout
|
33
|
+
if request.accepts.find {|mt| mt == 'xml'}
|
34
|
+
'wap'
|
35
|
+
else
|
36
|
+
# Firefox
|
37
|
+
#<Mime::Type:0xb79cd374 @synonyms=["application/xhtml+xml"], @string="text/html", @symbol=:html>
|
38
|
+
#<Mime::Type:0xb79cd1e4 @synonyms=["text/xml", "application/x-xml"], @string="application/xml", @symbol=:xml>
|
39
|
+
#<Mime::Type:0xb746d16c @synonyms=[], @string="image/png", @symbol=nil>
|
40
|
+
#<Mime::Type:0xb79cd3ec @synonyms=[], @string="text/plain", @symbol=:text>
|
41
|
+
#<Mime::Type:0xb79cd43c @synonyms=[], @string="*/*", @symbol=:all>
|
42
|
+
|
43
|
+
# nokia N80
|
44
|
+
#<Mime::Type:0xb79ab374 @synonyms=["application/xhtml+xml"], @string="text/html", @symbol=:html>
|
45
|
+
#<Mime::Type:0xb7308408 @synonyms=[], @string="text/css", @symbol=nil>
|
46
|
+
#<Mime::Type:0xb73082f0 @synonyms=[], @string="text/x-vcard", @symbol=nil>
|
47
|
+
#<Mime::Type:0xb73081ec @synonyms=[], @string="text/x-vcalendar", @symbol=nil>
|
48
|
+
#<Mime::Type:0xb73080d4 @synonyms=[], @string="image/gif", @symbol=nil>
|
49
|
+
#<Mime::Type:0xb7307fd0 @synonyms=[], @string="image/vnd.wap.wbmp", @symbol=nil>
|
50
|
+
#<Mime::Type:0xb79ab43c @synonyms=[], @string="*/*", @symbol=:all>
|
51
|
+
|
52
|
+
# SonyEricson K810i
|
53
|
+
#<Mime::Type:0xb72509d4 @synonyms=[], @string="multipart/mixed", @symbol=nil>
|
54
|
+
#<Mime::Type:0xb7250934 @synonyms=[], @string="application/vnd.wap.multipart.mixed", @symbol=nil>
|
55
|
+
#<Mime::Type:0xb7250880 @synonyms=[], @string="application/vnd.wap.xhtml+xml", @symbol=nil>
|
56
|
+
#<Mime::Type:0xb79ab374 @synonyms=["application/xhtml+xml"], @string="text/html", @symbol=:html>
|
57
|
+
#<Mime::Type:0xb72507cc @synonyms=[], @string="text/vnd.wap.wml", @symbol=nil>
|
58
|
+
#<Mime::Type:0xb73082f0 @synonyms=[], @string="text/x-vcard", @symbol=nil>
|
59
|
+
#<Mime::Type:0xb73081ec @synonyms=[], @string="text/x-vcalendar", @symbol=nil>
|
60
|
+
#<Mime::Type:0xb73080d4 @synonyms=[], @string="image/gif", @symbol=nil>
|
61
|
+
#<Mime::Type:0xb7307fd0 @synonyms=[], @string="image/vnd.wap.wbmp", @symbol=nil>
|
62
|
+
#<Mime::Type:0xb79ab43c @synonyms=[], @string="*/*", @symbol=:all>
|
63
|
+
|
64
|
+
'mwrt002'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def detour_to(options)
|
69
|
+
store_detour(params)
|
70
|
+
redirect_to(options)
|
71
|
+
end
|
72
|
+
|
73
|
+
def rjs_detour_to(options)
|
74
|
+
store_detour(params, request.post?)
|
75
|
+
rjs_redirect_to(options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def rjs_redirect_to(options)
|
79
|
+
@options = options
|
80
|
+
render :template => 'redirect', :layout => false
|
81
|
+
end
|
82
|
+
|
83
|
+
def store_detour(options, post = false)
|
84
|
+
options[:request_method] = :post if post
|
85
|
+
if session[:detours] && session[:detours].last == options
|
86
|
+
logger.debug "duplicate detour: #{options}"
|
87
|
+
return
|
88
|
+
end
|
89
|
+
logger.debug "adding detour: #{options}"
|
90
|
+
session[:detours] ||= []
|
91
|
+
session[:detours] << options
|
92
|
+
end
|
93
|
+
|
94
|
+
def store_detour_from_params
|
95
|
+
if params[:detour]
|
96
|
+
store_detour(params[:detour])
|
97
|
+
end
|
98
|
+
if params[:return_from_detour] && session[:detours]
|
99
|
+
pop_detour
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def back_or_redirect_to(options)
|
104
|
+
if session[:detours]
|
105
|
+
detour = pop_detour
|
106
|
+
post = detour.delete(:request_method) == :post
|
107
|
+
if post
|
108
|
+
redirect_to_post(detour)
|
109
|
+
else
|
110
|
+
redirect_to detour
|
111
|
+
end
|
112
|
+
else
|
113
|
+
redirect_to options
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def pop_detour
|
118
|
+
detours = session[:detours]
|
119
|
+
return nil unless detours
|
120
|
+
detour = detours.pop
|
121
|
+
logger.debug "popped detour: #{detour.inspect} #{session[:detours].size} more"
|
122
|
+
if detours.empty?
|
123
|
+
session[:detours] = nil
|
124
|
+
end
|
125
|
+
detour
|
126
|
+
end
|
127
|
+
private :pop_detour
|
128
|
+
|
129
|
+
def populate_shortcuts
|
130
|
+
@shortcuts = [
|
131
|
+
{:key => 'Alt-N', :function => :new_task, :options => {:controller => 'tasks', :action => 'new', :period_id => (@period ? @period.id : (@backlog && @backlog.periods.first ? @backlog.periods.first.id : nil))}},
|
132
|
+
{:key => 'Alt-Shift-N', :function => :new_period, :options => {:controller => 'periods', :action => 'new'}},
|
133
|
+
{:key => 'Alt-Ctrl-N', :function => :new_backlog, :options => {:controller => 'backlogs', :action => 'new'}},
|
134
|
+
{:key => 'Alt-Ctrl-G', :function => :new_group, :options => {:controller => 'groups', :action => :new}},
|
135
|
+
{:key => "Alt-#{l :up}", :function => :up},
|
136
|
+
{:key => "Alt-#{l :down}", :function => :down},
|
137
|
+
{:key => "Alt-Shift-#{l :left}", :function => :move_to_top},
|
138
|
+
{:key => "Alt-Shift-#{l :right}", :function => :move_to_bottom},
|
139
|
+
{:key => 'Alt-X', :function => :complete},
|
140
|
+
{:key => 'Alt-Q', :function => :reopen},
|
141
|
+
]
|
142
|
+
end
|
143
|
+
|
144
|
+
def populate_layout
|
145
|
+
return true if request.path_parameters[:action] =~ /_no_layout$/
|
146
|
+
|
147
|
+
populate_shortcuts
|
148
|
+
|
149
|
+
# TODO (uwe): This does not scale!
|
150
|
+
#periods = Period.find(:all).select {|period| period.active_or_future?(true) && period.party.includes?(user)}
|
151
|
+
periods = Period.find_active_or_future(true)
|
152
|
+
|
153
|
+
|
154
|
+
@sidebars = periods.sort_by {|p| p.required_speed}.reverse.map do |period|
|
155
|
+
content = '<ul>'
|
156
|
+
period.tasks.select {|task| task.in_list? }[0...5].map do |task|
|
157
|
+
"<li>#{task.description}</li>"
|
158
|
+
end.each do |period_link|
|
159
|
+
content << "#{period_link}"
|
160
|
+
end
|
161
|
+
content << "</ul>\n"
|
162
|
+
content << drop_receiving_element("sidebar_#{period.id}",
|
163
|
+
:url => with_detour({:action => "move_task_to_period", :period_id => period.id, :layout => false}),
|
164
|
+
:accept => "tasks", :loading => "", :complete => "",
|
165
|
+
:hoverclass => 'highlight')
|
166
|
+
|
167
|
+
{ :id => period.id,
|
168
|
+
:title => "#{period.party.name}##{period.position} (#{'%0.1f' % period.required_speed})",
|
169
|
+
:options => {:controller => 'periods', :action => :show, :id => period},
|
170
|
+
:content => content
|
171
|
+
}
|
172
|
+
end
|
173
|
+
started_tasks = Task.find_started
|
174
|
+
if not started_tasks.empty?
|
175
|
+
links = started_tasks.map do |task|
|
176
|
+
"<li><a href=\"#{url_for :controller => 'tasks', :action => :list_started, :id => task.id}\">#{task.description}</a></li>"
|
177
|
+
end
|
178
|
+
@sidebars.unshift({ :title => l(:started_tasks),
|
179
|
+
:options => {:controller => 'tasks', :action => :list_started},
|
180
|
+
:content => "<ul>#{links}"
|
181
|
+
})
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def user_id
|
188
|
+
session[:user_id]
|
189
|
+
end
|
190
|
+
|
191
|
+
def user
|
192
|
+
User.find_by_id(user_id) if user_id
|
193
|
+
end
|
194
|
+
|
195
|
+
def redirect_to_post(options)
|
196
|
+
url = url_for options
|
197
|
+
render :text => <<EOF, :layout => false
|
198
|
+
<html>
|
199
|
+
<body onload="alert('submitting');document.getElementById('form').submit()">
|
200
|
+
<form id="form" action="#{url}" method="POST">
|
201
|
+
</form>
|
202
|
+
</body>
|
203
|
+
</html>
|
204
|
+
EOF
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -130,12 +130,16 @@ class PeriodsController < ApplicationController
|
|
130
130
|
next_task = @task.higher_item ? @task.higher_item : @task.lower_item ? @task.lower_item : @task
|
131
131
|
@task.move_to_period period
|
132
132
|
load_tasks(@task.period)
|
133
|
-
|
133
|
+
if request.xhr?
|
134
|
+
render :action => :move_task_to_period, :layout => false
|
135
|
+
else
|
136
|
+
redirect_to :action => :show, :id => @task.period, :task_id => @task.id, :layout => false
|
137
|
+
end
|
134
138
|
else
|
135
|
-
rjs_detour_to :
|
139
|
+
rjs_detour_to :action => :new, :period => {:party_id => @task.period.party_id}, :layout => false
|
136
140
|
end
|
137
141
|
else
|
138
|
-
redirect_to :
|
142
|
+
redirect_to :action => :show, :id => @task.period, :task_id => @task.id, :layout => false
|
139
143
|
end
|
140
144
|
end
|
141
145
|
|
data/app/models/task.rb
CHANGED
@@ -348,17 +348,15 @@ class Task < ActiveRecord::Base
|
|
348
348
|
new_work.task = self
|
349
349
|
|
350
350
|
new_work.started_at = Time.previous_quarter
|
351
|
-
if works.size > 0
|
352
351
|
if current_user
|
353
|
-
last_work = works.
|
354
|
-
|
355
|
-
|
356
|
-
last_work = works.select {|work| work.user.nil?}.last
|
352
|
+
last_work = current_user.works.last
|
353
|
+
else
|
354
|
+
last_work = Work.find(:first, :order => 'compeleted_at DESC')
|
357
355
|
end
|
358
356
|
if last_work && last_work.completed_at > new_work.started_at
|
359
357
|
new_work.started_at = last_work.completed_at
|
360
358
|
end
|
361
|
-
|
359
|
+
|
362
360
|
new_work.user = current_user
|
363
361
|
new_work.work_account_id = work_account.id
|
364
362
|
new_work.save!
|
data/app/models/user.rb
CHANGED
@@ -9,6 +9,7 @@ class User < Party
|
|
9
9
|
# even if they follow the defaults since ClassTableInheritanceInRails breaks it.
|
10
10
|
has_and_belongs_to_many :groups, :join_table => "groups_users", :foreign_key => "user_id", :association_foreign_key => 'group_id'
|
11
11
|
has_and_belongs_to_many :work_lock_subscribers, :class_name => 'User', :join_table => "user_work_lock_subscriptions", :foreign_key => "user_id", :association_foreign_key => 'subscriber_user_id'
|
12
|
+
has_many :works, :foreign_key => :user_id, :order => :completed_at
|
12
13
|
has_many :work_locks, :foreign_key => :user_id, :order => :end_on
|
13
14
|
|
14
15
|
attr_accessor :password_needs_confirmation
|
@@ -1,16 +1,18 @@
|
|
1
1
|
class WorkLockNagger
|
2
2
|
include ActionController::UrlWriter
|
3
3
|
|
4
|
-
puts "Loading class"
|
5
|
-
|
6
4
|
def initialize
|
7
|
-
puts "Worker initialized"
|
8
5
|
end
|
9
6
|
|
10
7
|
def nag
|
11
|
-
|
8
|
+
sleep 1.minute
|
9
|
+
puts "Work Lock Nagger started"
|
12
10
|
begin
|
13
|
-
|
11
|
+
host = Socket::gethostbyname('localhost')[1][1]
|
12
|
+
config = YAML::load(ERB.new(IO.read(APP_CONFIG_FILE)).result) || {}
|
13
|
+
port = config[:port] || 3000
|
14
|
+
|
15
|
+
url = url_for(:host => host, :port => port, :controller => 'works', :action => :weekly_work_sheet_by_work_account)
|
14
16
|
rescue Exception => e
|
15
17
|
puts e.message
|
16
18
|
puts e.backtrace
|
data/bin/backlog
CHANGED
@@ -114,23 +114,31 @@ when 'status'
|
|
114
114
|
exit 3
|
115
115
|
end
|
116
116
|
when 'setup_unix'
|
117
|
+
puts "Starting setup on #{RUBY_PLATFORM}"
|
118
|
+
bsd = ARGV[1..-1].include? 'bsd'
|
119
|
+
debug = ARGV[1..-1].include? 'debug'
|
120
|
+
pg_admin_user = bsd ? 'pgsql' : 'postgres'
|
117
121
|
current_user = `whoami`
|
118
|
-
users = `su -
|
122
|
+
users = `su - #{pg_admin_user} -c "echo '\\du' | psql template1"`
|
123
|
+
raise "Could not list users: #{$? >> 8}:#{$? & 0xff}" unless ($? >> 8) == 0
|
119
124
|
unless users =~ /root/
|
120
125
|
puts users
|
121
126
|
createuser_command = `which createuser`.chomp
|
122
|
-
puts `su -
|
127
|
+
puts `su - #{pg_admin_user} -c "#{createuser_command} -dAR #{current_user}"`
|
123
128
|
end
|
124
|
-
dbs = `su -
|
129
|
+
dbs = `su - #{pg_admin_user} -c "echo '\\l' | psql template1"`
|
125
130
|
unless dbs =~ /#{APPLICATION}_production/
|
126
131
|
puts dbs
|
127
132
|
createdb_command = `which createdb`.chomp
|
128
|
-
puts `su -
|
133
|
+
puts `su - #{pg_admin_user} -c "#{createdb_command} #{APPLICATION}_production"`
|
134
|
+
raise "Could not create database: #{$? >> 8}:#{$? & 0xff}" unless ($? >> 8) == 0
|
129
135
|
end
|
136
|
+
FileUtils.mkdir_p INSTALL_DIR
|
130
137
|
Dir.chdir INSTALL_DIR
|
131
138
|
Dir.mkdir LOG_DIR unless File.exists? LOG_DIR
|
132
139
|
ENV['RAILS_ENV'] = 'production'
|
133
|
-
puts `rake db:migrate`
|
140
|
+
puts `rake db:migrate #{'--trace' if debug}`
|
141
|
+
raise "Could not migrate database: #{$? >> 8}:#{$? & 0xff}" unless ($? >> 8) == 0
|
134
142
|
|
135
143
|
# TODO: provide startup information based on launchd in OS X versions >= 10.4
|
136
144
|
if File.directory? '/etc/init.d'
|
@@ -144,7 +152,7 @@ when 'setup_unix'
|
|
144
152
|
`su - -c "chkconfig #{APPLICATION} on"`
|
145
153
|
puts
|
146
154
|
else
|
147
|
-
puts "Usage: #$0 {start|stop|restart|status|setup_unix}"
|
155
|
+
puts "Usage: #$0 {start|stop|restart|status|setup_unix [bsd] [debug]}"
|
148
156
|
exit 1
|
149
157
|
end
|
150
158
|
|
data/etc/backlog.conf
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
+
# Uncomment the following line to set the public url for this server.
|
2
|
+
# Default url is http://localhost:3000/
|
3
|
+
|
4
|
+
# Examples:
|
5
|
+
# app_url: http://localhost:3000/
|
6
|
+
# app_url: http://myhost.mydomain/
|
7
|
+
# app_url: http://myhost.mydomain/backlog
|
8
|
+
|
1
9
|
# Uncomment the following line to override the network port to listen on.
|
2
10
|
# Default port is 3000.
|
3
11
|
|
4
12
|
# port: 3000
|
5
13
|
|
6
|
-
# Uncomment
|
14
|
+
# Uncomment _one_ of the following sections to override the database connection settings.
|
7
15
|
|
8
16
|
# database:
|
9
17
|
# adapter: postgresql
|
@@ -126,15 +126,19 @@ class PeriodsControllerTest < Test::Unit::TestCase
|
|
126
126
|
|
127
127
|
post :move_task_to_next_period, :id => tasks(:another).id
|
128
128
|
|
129
|
-
assert_response :
|
129
|
+
assert_response :redirect
|
130
130
|
|
131
|
-
|
132
|
-
|
131
|
+
check_move_effects(before, :future)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_move_task_to_next_period_xhr
|
135
|
+
before = Task.find(tasks(:another).id)
|
133
136
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
137
|
+
xhr :post, :move_task_to_next_period, :id => tasks(:another).id
|
138
|
+
|
139
|
+
assert_response :success
|
140
|
+
|
141
|
+
check_move_effects(before, :future)
|
138
142
|
end
|
139
143
|
|
140
144
|
def test_move_task_to_next_period_from_past
|
@@ -143,15 +147,20 @@ class PeriodsControllerTest < Test::Unit::TestCase
|
|
143
147
|
|
144
148
|
post :move_task_to_next_period, :id => task.id
|
145
149
|
|
146
|
-
assert_response :
|
150
|
+
assert_response :redirect
|
147
151
|
|
148
|
-
|
149
|
-
|
152
|
+
check_move_effects(before, :active)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_move_task_to_next_period_from_past_xhr
|
156
|
+
task = tasks(:first)
|
157
|
+
before = Task.find(task.id)
|
150
158
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
159
|
+
xhr :post, :move_task_to_next_period, :id => task.id
|
160
|
+
|
161
|
+
assert_response :success
|
162
|
+
|
163
|
+
check_move_effects(before, :active)
|
155
164
|
end
|
156
165
|
|
157
166
|
def test_move_to_next_period_at_end
|
@@ -175,17 +184,20 @@ class PeriodsControllerTest < Test::Unit::TestCase
|
|
175
184
|
|
176
185
|
post :move_task_to_next_period, :id => before.id
|
177
186
|
|
178
|
-
assert_response :
|
187
|
+
assert_response :redirect
|
179
188
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
189
|
+
check_move_effects(before, :active)
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_move_to_next_period_from_ancient_xhr
|
193
|
+
before = tasks(:in_ancient)
|
194
|
+
previous_last_id = Task.find(:first, :order => 'id DESC').id
|
195
|
+
|
196
|
+
xhr :post, :move_task_to_next_period, :id => before.id
|
197
|
+
|
198
|
+
assert_response :success
|
184
199
|
|
185
|
-
|
186
|
-
assert_not_nil new
|
187
|
-
assert_equal before.id, new.previous_task_id
|
188
|
-
assert_equal 1, new.position
|
200
|
+
check_move_effects(before, :active)
|
189
201
|
end
|
190
202
|
|
191
203
|
def test_move_task_to_period_back_to_earlier_period
|
@@ -253,4 +265,23 @@ class PeriodsControllerTest < Test::Unit::TestCase
|
|
253
265
|
assert_nil after.resolution
|
254
266
|
end
|
255
267
|
|
268
|
+
private
|
269
|
+
|
270
|
+
def check_move_effects(before, period_sym)
|
271
|
+
after = Task.find(before.id)
|
272
|
+
assert_equal before.period_id, after.period_id
|
273
|
+
assert_equal Task::POSTPONED, after.resolution
|
274
|
+
assert_not_nil after.finished_at
|
275
|
+
|
276
|
+
newest_task = Task.find(:first, :order => 'id DESC')
|
277
|
+
new_task = Task.find_by_period_id_and_previous_task_id(periods(period_sym).id, before.id)
|
278
|
+
assert_not_nil newest_task
|
279
|
+
assert_not_nil new_task
|
280
|
+
assert_equal newest_task.id, new_task.id
|
281
|
+
assert_equal before.previous_task_id || before.id, new_task.previous_task_id
|
282
|
+
assert_nil new_task.finished_at
|
283
|
+
assert_nil new_task.resolution
|
284
|
+
assert_equal 1, new_task.position
|
285
|
+
end
|
286
|
+
|
256
287
|
end
|
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.
|
4
|
+
version: 0.21.2
|
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-
|
12
|
+
date: 2008-02-08 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -64,7 +64,7 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: 1.
|
67
|
+
version: 1.5.0
|
68
68
|
version:
|
69
69
|
description: Backlog is a tool to help you collect and organize all your tasks, whether you are a single person or a small or large group. A time keeping module is also included to track time spent on the different tasks.
|
70
70
|
email: uwe@kubosch.no
|
@@ -209,6 +209,7 @@ files:
|
|
209
209
|
- app/controllers/welcome_controller.rb
|
210
210
|
- app/controllers/backlogs_controller.rb
|
211
211
|
- app/controllers/estimates_controller.rb
|
212
|
+
- app/controllers/application.rb~
|
212
213
|
- app/controllers/application.rb
|
213
214
|
- app/controllers/parties_controller.rb
|
214
215
|
- app/controllers/periods_controller.rb
|