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 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
- redirect_to detour
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
- end
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
- render :action => :move_task_to_period, :layout => false
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 :controller => 'periods', :action => :new, :period => {:party_id => @task.period.party_id}, :layout => false
139
+ rjs_detour_to :action => :new, :period => {:party_id => @task.period.party_id}, :layout => false
136
140
  end
137
141
  else
138
- redirect_to :controller => 'periods', :action => :show, :id => @task.period, :task_id => @task.id, :layout => false
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.select {|work| work.user == current_user}.last
354
- end
355
- unless last_work
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
- end
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
- puts "Nag called"
8
+ sleep 1.minute
9
+ puts "Work Lock Nagger started"
12
10
  begin
13
- url = url_for(:host => 'localhost', :port => 3000, :controller => 'works', :action => :weekly_work_sheet_by_work_account)
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 - postgres -c "echo '\\du' | psql template1"`
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 - postgres -c "#{createuser_command} -dAR #{current_user}"`
127
+ puts `su - #{pg_admin_user} -c "#{createuser_command} -dAR #{current_user}"`
123
128
  end
124
- dbs = `su - postgres -c "echo '\\l' | psql template1"`
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 - postgres -c "#{createdb_command} #{APPLICATION}_production"`
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 one of the following sections to override the database connection settings.
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 :success
129
+ assert_response :redirect
130
130
 
131
- after = Task.find(tasks(:another).id)
132
- assert_equal tasks(:another).period_id, after.period_id
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
- new_task = Task.find_by_period_id_and_previous_task_id(periods(:future).id, before.id)
135
- assert_nil new_task.finished_at
136
- assert_nil new_task.resolution
137
- assert_equal 1, new_task.position
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 :success
150
+ assert_response :redirect
147
151
 
148
- after = Task.find(task.id)
149
- assert_equal task.period_id, after.period_id
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
- new_task = Task.find_by_period_id_and_previous_task_id(periods(:active).id, task.id)
152
- assert_nil new_task.finished_at
153
- assert_nil new_task.resolution
154
- assert_equal 1, new_task.position
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 :success
187
+ assert_response :redirect
179
188
 
180
- after = Task.find(before.id)
181
- assert_equal before.period_id, after.period_id
182
- assert_equal Task::POSTPONED, after.resolution
183
- assert_not_nil after.finished_at
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
- new = Task.find(:first, :order => 'id DESC', :conditions => "id > #{previous_last_id}")
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.1
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-05 00:00:00 +01:00
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.4.0
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