backlog 0.15.1 → 0.16.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.
Files changed (37) hide show
  1. data/History.txt +16 -0
  2. data/app/controllers/backlogs_controller.rb +2 -2
  3. data/app/controllers/estimates_controller.rb +3 -4
  4. data/app/controllers/periods_controller.rb +14 -2
  5. data/app/controllers/tasks_controller.rb +6 -1
  6. data/app/controllers/user_controller.rb +10 -10
  7. data/app/helpers/application_helper.rb +3 -2
  8. data/app/helpers/user_helper.rb +4 -4
  9. data/app/views/layouts/_headers.rhtml +1 -0
  10. data/app/views/layouts/_notice.rhtml +1 -4
  11. data/app/views/periods/_show_active.rhtml +8 -6
  12. data/app/views/periods/show.rhtml +38 -0
  13. data/app/views/tasks/_backlog_header.rhtml +7 -7
  14. data/app/views/tasks/_completed.rhtml +3 -3
  15. data/app/views/tasks/_fields_header.rhtml +9 -9
  16. data/app/views/tasks/_form.rhtml +16 -6
  17. data/app/views/tasks/_task.rhtml +56 -60
  18. data/app/views/tasks/edit.rhtml +67 -1
  19. data/app/views/tasks/notes.rhtml +6 -2
  20. data/bin/backlog +63 -1
  21. data/db/migrate/025_add_simple_auditing_of_tasks.rb +11 -0
  22. data/db/schema.rb +5 -1
  23. data/lib/url_for_fix.rb +5 -5
  24. data/public/applets/bsf.jar +0 -0
  25. data/public/applets/jruby.jar +0 -0
  26. data/public/javascripts/ruby.js +46 -0
  27. data/test/functional/user_controller_test.rb +5 -5
  28. data/vendor/plugins/foreign_key_migrations/CHANGELOG +36 -0
  29. data/vendor/plugins/foreign_key_migrations/README +27 -0
  30. data/vendor/plugins/foreign_key_migrations/about.yml +5 -0
  31. data/vendor/plugins/foreign_key_migrations/init.rb +1 -2
  32. data/vendor/plugins/foreign_key_migrations/lib/foreign_key_migrations.rb +3 -0
  33. data/vendor/plugins/foreign_key_migrations/lib/red_hill_consulting/foreign_key_migrations/active_record/base.rb +22 -0
  34. data/vendor/plugins/foreign_key_migrations/lib/red_hill_consulting/foreign_key_migrations/active_record/connection_adapters/abstract_adapter.rb +22 -0
  35. data/vendor/plugins/foreign_key_migrations/lib/red_hill_consulting/foreign_key_migrations/active_record/connection_adapters/table_definition.rb +28 -0
  36. metadata +99 -80
  37. data/vendor/plugins/foreign_key_migrations/lib/red_hill_consulting/foreign_key_migrations.rb +0 -57
@@ -1,5 +1,71 @@
1
+ <% @page_title = "#{l :editing} #{l :task}" -%>
2
+
1
3
  <div id="spotlight">
2
- <% @page_title = "#{l :editing} #{l :task}" %>
4
+ <div class="btitle" style="float: left; width: 70%">
5
+ <h4><%=l :task %> #<%=@task.id%></h4>
6
+ </div>
7
+
8
+ <% if @task.finished? -%>
9
+ <div style="float:right">
10
+ Task is finished.
11
+ </div>
12
+ <% else -%>
13
+ <div style="float: left" style="border: 0px">
14
+ <% if @task.enable_subtasks? && (@task.period.nil? || @task.period.active_or_future?) %>
15
+ <% form_tag({:controller => 'tasks', :action => :specify, :id => @task}) do %>
16
+ <%= image_button_to('add.png', l(:specify), :controller => 'tasks', :action => :specify, :id => @task.id)%>
17
+ <% end %>
18
+ <% end %>
19
+ </div>
20
+ <div style="float: left" style="border: 0px">
21
+ <%=("&nbsp;" * @task.depth * 4) if @task.depth > 0 %>
22
+ <%=resolution_image(@task.resolution) if @task.finished_at %>
23
+ <%="-" if @task.children.size > 0 %>
24
+ </div>
25
+
26
+
27
+
28
+ <div style="float: right" style="border: 1px solid black">
29
+ <div style="float: left" style="border: 1px solid black">
30
+ <% if @task.loggable? -%>
31
+ <% if @task.work_started? -%>
32
+ <% remote_form_for(:work, :url => {:controller => 'works', :action => 'update_time', :id => @task.started_work}) do |f| %>
33
+ <%=submit_tag('checkmark', :value => l(:save), :style => 'display: none')%>
34
+ <%=l :started_at%> <%=f.text_field 'started_at_time', :id => "work_#{@task.started_work.id}_started_at_time", :value => @task.started_work.started_at.strftime('%H:%M'),
35
+ :class => :task_time, :maxlength => 5 %>
36
+ <% end %>
37
+ <% elsif @task.track_times? && (@task.period_id.nil? || @task.period.active?) %>
38
+ <%=image_link_to_remote 'hammer.png', l(:start_work), {:controller => 'tasks', :action => :start_work, :id => @task.id}, nil, true %>
39
+ <% end -%>
40
+ <% end -%>
41
+ </div>
42
+ <div style="float: left" style="border: 1px solid black">
43
+ <% if @task.loggable? && @task.work_started? -%>
44
+ <% form_tag({:controller => 'works', :action => 'update', :id => @task.started_work}) do %>
45
+ <%= image_detour_to('ernes_stop.png', l(:end_work), {:controller => 'tasks', :action => :end_work, :id => @task.id}, nil, true) %>
46
+ <% end -%>
47
+ <% end -%>
48
+ </div>
49
+ <div style="float: left" align="right" style="border: 1px solid black">
50
+ <% if @task.active? -%>
51
+ <% if @task.loggable? -%>
52
+ <% unless @task.work_started? -%>
53
+ <%# form_tag({:controller => 'tasks', :action => 'update', :id => @task}) do -%>
54
+ <%=image_link_to_remote('arrow_right.png', l(:move_to_next_period), {:action => :move_task_to_next_period, :id => @task}, nil, true) if @task.backlog.enable_periods? || @task.period_id%>
55
+ <%=image_link_to_remote('ernes_stop.png', l(:abort), {:action => :abort_task, :id => @task}, nil, true)%>
56
+ <%# end -%>
57
+ <% end -%>
58
+ <% end -%>
59
+ <% elsif (@task.period.nil? || (not @task.period.passed?)) && @task.leaf? -%>
60
+ <% form_tag({:controller => 'tasks', :action => 'update', :id => @task}) do -%>
61
+ <%=image_link_to_remote('eraser.png', l(:reopen), {:action => :reopen_task, :id => @task}, nil, true) %>
62
+ <% end -%>
63
+ <% end -%>
64
+ </div>
65
+ </div>
66
+ <% end -%>
67
+
68
+ <br clear="all" />
3
69
 
4
70
  <% form_tag({:action => 'update', :id => @task}, :multipart => true) do %>
5
71
  <%= render :partial => 'form' %>
@@ -1,7 +1,11 @@
1
- <div id="spotlight">
1
+ <div id="spotlight" style="text-align: left;">
2
2
  <% @page_title = "#{l :notes} #{l :task} ##{@task.id}" %>
3
3
 
4
- <pre style="text-align: left;">
4
+ <div class="btitle">
5
+ <h3><%=l :task%> #<%=@task.id%>: <%=@task.description -%></h3>
6
+ </div>
7
+
8
+ <pre>
5
9
  <%=h @task.notes %>
6
10
  </pre>
7
11
 
data/bin/backlog CHANGED
@@ -15,6 +15,11 @@ require 'rbconfig'
15
15
 
16
16
  APPLICATION = 'backlog'
17
17
 
18
+ STATUS_STOPPED = 0
19
+ STATUS_RUNNING = 1
20
+ STATUS_STALE = 2
21
+ STATUS_NOT_ROOT = 3
22
+
18
23
  if gem = Gem::searcher.find(APPLICATION)
19
24
  INSTALL_DIR = "#{Gem.dir}/gems/#{APPLICATION}-#{gem.version}"
20
25
  else
@@ -31,6 +36,23 @@ PID_FILE = '/var/run/backlog.pid'
31
36
  def start(config)
32
37
  File.makedirs LOG_DIR unless File.exists? LOG_DIR
33
38
  File.makedirs File.dirname(PID_FILE) unless File.exists? File.dirname(PID_FILE)
39
+
40
+ status = get_status
41
+ case status
42
+ when STATUS_RUNNING:
43
+ puts "Process already running. Stopping."
44
+ exit 1
45
+ when STATUS_STALE:
46
+ puts "Deleting stale PID file."
47
+ File.delete(PID_FILE)
48
+ when STATUS_STOPPED:
49
+ when STATUS_NOT_ROOT:
50
+ puts "Permission denied. Please run as root/administrator."
51
+ exit 6
52
+ else
53
+ puts "Unknown status: #{status}. Stopping"
54
+ exit 2
55
+ end
34
56
  `mongrel_rails start -p #{config['port'] || 3000} -e production -c #{INSTALL_DIR} -d -m #{INSTALL_DIR}/config/mime_types.yaml -P #{PID_FILE} 1>#{LOG_DIR}/stdout.log 2>#{LOG_DIR}/stderr.log`
35
57
  end
36
58
 
@@ -38,6 +60,30 @@ def stop(config)
38
60
  `mongrel_rails stop -c #{INSTALL_DIR} -P #{PID_FILE}`
39
61
  end
40
62
 
63
+ def get_pid
64
+ if File.exists? PID_FILE
65
+ return File.readlines(PID_FILE)[0].to_i
66
+ else
67
+ return nil
68
+ end
69
+ end
70
+
71
+ def get_status
72
+ pid = get_pid
73
+ if pid
74
+ begin
75
+ Process.kill(0, pid)
76
+ return STATUS_RUNNING
77
+ rescue Errno::ESRCH
78
+ return STATUS_STALE
79
+ rescue Errno::EPERM
80
+ return STATUS_NOT_ROOT
81
+ end
82
+ else
83
+ return STATUS_STOPPED
84
+ end
85
+ end
86
+
41
87
  # See how we were called.
42
88
  case ARGV[0]
43
89
  when 'start':
@@ -50,7 +96,23 @@ when 'restart':
50
96
  when 'reload':
51
97
  puts `mongrel_rails restart -c #{INSTALL_DIR} -P #{PID_FILE}`
52
98
  when 'status'
53
- puts `ps -ef | grep backlog`
99
+ case get_status
100
+ when STATUS_RUNNING:
101
+ puts "#{APPLICATION} is running as pid #{get_pid}."
102
+ exit 0
103
+ when STATUS_STOPPED:
104
+ puts "#{APPLICATION} is stopped."
105
+ exit 5
106
+ when STATUS_STALE:
107
+ puts "#{APPLICATION} is stopped but PID file exists with pid #{get_pid}."
108
+ exit 4
109
+ when STATUS_NOT_ROOT:
110
+ puts "Permission denied. Please run as root/administrator."
111
+ exit 6
112
+ else
113
+ puts "Unknown status #{get_status}."
114
+ exit 3
115
+ end
54
116
  when 'setup_unix'
55
117
  current_user = `whoami`
56
118
  users = `su - postgres -c "echo '\\du' | psql template1"`
@@ -0,0 +1,11 @@
1
+ class AddSimpleAuditingOfTasks < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :tasks, :created_by, :integer, :references => [:users, :party_id]
4
+ add_column :tasks, :updated_by, :integer, :references => [:users, :party_id]
5
+ end
6
+
7
+ def self.down
8
+ remove_column :tasks, :updated_by
9
+ remove_column :tasks, :created_by
10
+ end
11
+ end
data/db/schema.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # migrations feature of ActiveRecord to incrementally modify your database, and
3
3
  # then regenerate this schema definition.
4
4
 
5
- ActiveRecord::Schema.define(:version => 24) do
5
+ ActiveRecord::Schema.define(:version => 25) do
6
6
 
7
7
  create_table "backlogs", :force => true do |t|
8
8
  t.column "name", :string, :limit => 64, :null => false
@@ -75,6 +75,8 @@ ActiveRecord::Schema.define(:version => 24) do
75
75
  t.column "notes", :text
76
76
  t.column "work_account_id", :integer
77
77
  t.column "customer_id", :integer
78
+ t.column "created_by", :integer
79
+ t.column "updated_by", :integer
78
80
  end
79
81
 
80
82
  add_index "tasks", ["parent_id"], :name => "index_tasks_on_parent_id"
@@ -128,6 +130,8 @@ ActiveRecord::Schema.define(:version => 24) do
128
130
 
129
131
  add_foreign_key "task_files", ["task_id"], "tasks", ["id"], :name => "task_files_task_id_fkey"
130
132
 
133
+ add_foreign_key "tasks", ["updated_by"], "users", ["party_id"], :name => "tasks_updated_by_fkey"
134
+ add_foreign_key "tasks", ["created_by"], "users", ["party_id"], :name => "tasks_created_by_fkey"
131
135
  add_foreign_key "tasks", ["customer_id"], "customers", ["id"], :name => "tasks_customer_id_fkey"
132
136
  add_foreign_key "tasks", ["work_account_id"], "work_accounts", ["id"], :name => "tasks_work_account_id_fkey"
133
137
  add_foreign_key "tasks", ["backlog_id"], "backlogs", ["id"], :name => "tasks_backlog_id_fkey"
data/lib/url_for_fix.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module UrlForFix
2
- # TODO (uwe): Can be removed when using EdgeRails of Rails >= 1.3
2
+ # TODO (uwe): Can be removed when using EdgeRails or Rails >= 1.3
3
3
  def url_for(org_options = {}, *parameters_for_method_reference)
4
4
  return super(org_options, *parameters_for_method_reference) if org_options.nil? || org_options.is_a?(String)
5
5
  new_options = {}
@@ -15,12 +15,12 @@ module UrlForFix
15
15
  def add_option(options, param, value)
16
16
  case value
17
17
  when Hash:
18
- value.each do |key, value|
19
- add_option(options, "#{param}[#{key}]", value)
18
+ value.each do |key, v|
19
+ add_option(options, "#{param}[#{key}]", v)
20
20
  end
21
21
  when Array:
22
- hash.each do |value|
23
- add_option(options, "#{param}[]", value)
22
+ value.each do |v|
23
+ add_option(options, "#{param}[]", v)
24
24
  end
25
25
  else
26
26
  options[param] = value
Binary file
Binary file
@@ -0,0 +1,46 @@
1
+ var Ruby = {
2
+ code: function() {
3
+ var scripts = document.getElementsByTagName("script");
4
+ var rubyCode = '';
5
+
6
+ for (var i = 0; i < scripts.length; i++) {
7
+ var script = scripts[i];
8
+ if ( (script.getAttribute("type") == "text/ruby") || (script.getAttribute("type") == "text/x-ruby") ) {
9
+ rubyCode += script.innerHTML;
10
+ }
11
+ }
12
+ return rubyCode;
13
+ },
14
+
15
+ init: function(callback) {
16
+ Ruby.applet();
17
+ Ruby.evalScript(callback);
18
+ },
19
+
20
+ evalScript: function(callback) {
21
+ if (document.RubyApplet.evalRuby && document.RubyApplet.hasStarted()) {
22
+ callback(Ruby.eval(Ruby.code()));
23
+ } else {
24
+ setTimeout(function() {
25
+ Ruby.evalScript(callback);
26
+ }, 500);
27
+ }
28
+ },
29
+
30
+ eval: function(code) {
31
+ return document.RubyApplet.evalRuby(code);
32
+ },
33
+
34
+ applet: function() {
35
+ var applet = document.createElement('applet');
36
+ // applet.setAttribute("archive", "http://ruby-in-browser.googlecode.com/svn/trunk/lib/jruby.jar,http://ruby-in-browser.googlecode.com/svn/trunk/lib/asm.jar,http://ruby-in-browser.googlecode.com/svn/trunk/lib/backport-util-concurrent.jar");
37
+ applet.setAttribute("archive", "/java/jruby.jar,/java/bsf.jar");
38
+ applet.setAttribute("code", "RubyApplet");
39
+ applet.setAttribute("codebase", "http://ruby-in-browser.googlecode.com/svn/trunk/classes");
40
+ applet.setAttribute("name", "RubyApplet");
41
+ applet.setAttribute("width", "1");
42
+ applet.setAttribute("height", "1");
43
+
44
+ document.body.appendChild(applet);
45
+ }
46
+ };
@@ -9,7 +9,7 @@ class UserControllerTest < Test::Unit::TestCase
9
9
  include UserSystem
10
10
 
11
11
  self.use_transactional_fixtures = false
12
- fixtures :parties, :users, :groups, :groups_users, :backlogs, :periods, :tasks, :task_files, :estimates, :works
12
+ main_scenario
13
13
 
14
14
  def setup
15
15
  @controller = UserController.new
@@ -40,21 +40,21 @@ class UserControllerTest < Test::Unit::TestCase
40
40
  post :login, :user => { :login => "tesla", :password => "wrong password" }
41
41
  assert_not_logged_in
42
42
  assert_template 'login'
43
- assert_contains "Login failed", flash['message']
43
+ assert_contains "Login failed", flash[:notice]
44
44
  end
45
45
 
46
46
  def test_login__wrong_login
47
47
  post :login, :user => { :login => "wrong login", :password => "atest" }
48
48
  assert_not_logged_in
49
49
  assert_template 'login'
50
- assert_contains "Login failed", flash['message']
50
+ assert_contains "Login failed", flash[:notice]
51
51
  end
52
52
 
53
53
  def test_login__deleted_user_cant_login
54
54
  post :login, :user => { :login => "deleted_tesla", :password => "atest" }
55
55
  assert_not_logged_in
56
56
  assert_template 'login'
57
- assert_contains "Login failed", flash['message']
57
+ assert_contains "Login failed", flash[:notice]
58
58
  end
59
59
 
60
60
  def test_signup
@@ -82,7 +82,7 @@ class UserControllerTest < Test::Unit::TestCase
82
82
  :email => "newtesla@example.com"
83
83
  assert_not_logged_in
84
84
  assert_equal 0, ActionMailer::Base.deliveries.size
85
- assert_contains "confirmation email not sent", flash['message']
85
+ assert_contains "confirmation email not sent", flash[:notice]
86
86
  end
87
87
 
88
88
  def test_signup__mismatched_passwords
@@ -1,3 +1,39 @@
1
+ [REVISION 20071128]
2
+
3
+ [FIXED] Workaround to ensure plugin is only ever loaded once.
4
+
5
+ [REVISION 20070905]
6
+
7
+ [FIXED] "some_column_name" referenced in foreign key constraint does not exist.
8
+
9
+ [REVISION 20070904]
10
+
11
+ [NEW] Support :references keyword when calling primary_key().
12
+
13
+ [NEW] [#11995] the parameter :references needs the second argument referencing the field name.
14
+
15
+ [REVISION 20070707]
16
+
17
+ [NEW] Support acts_as_tree convention: if a column is named parent_id it will be treated as a circular reference to the table in which it is defined.
18
+
19
+ [REVISION 20070703]
20
+
21
+ [FIXED] Foreign-keys not created when using add_column.
22
+
23
+ [REVISION 20070628]
24
+
25
+ [FIXED] Stack level too deep in 'add_column_without_foreign_key_migrations' (Ronen Barzel).
26
+
27
+ [REVISION 20070503]
28
+
29
+ [NEW] Support for SQL92 [NOT] DEFERRABLE on foreign keys.
30
+
31
+ [REVISION 20061202]
32
+
33
+ [CHANGED] Use Rails 1.2 alias_method_chain.
34
+
35
+ [CHANGED] Separate modules into individual files.
36
+
1
37
  [REVISION 20061013]
2
38
 
3
39
  [NEW] install.rb informs user of missing dependencies.
@@ -30,6 +30,14 @@ foreign-key to be generated, you can use <code>:references => nil</code>:
30
30
  ...
31
31
  end
32
32
 
33
+ Sometimes you may (for legacy reasons) need to reference a primary key column that is
34
+ named something other than +id+. In this case you can specify the name of the column:
35
+
36
+ create_table :orders do |t|
37
+ t.column :ordered_by_pk, :integer, :null => false, :references => [:customers, :pk]
38
+ ...
39
+ end
40
+
33
41
  You also have the option of specifying what to do on delete/update using
34
42
  <code>:on_delete</code>/<code>:on_update</code>, respectively to one of:
35
43
  <code>:cascade</code>; <code>:restrict</code>; and <code>:set_null</code>:
@@ -39,6 +47,25 @@ You also have the option of specifying what to do on delete/update using
39
47
  ...
40
48
  end
41
49
 
50
+ If your database supports it (for example PostgreSQL) you can also mark the constraint as deferrable:
51
+
52
+ create_table :orders do |t|
53
+ t.column :customer_id, :integer, :deferrable => true
54
+ ...
55
+ end
56
+
57
+ By convention, if a column is named +parent_id+ it will be treated as a circular reference to
58
+ the table in which it is defined.
59
+
60
+ Sometimes you may (for legacy reasons) need to name your primary key column such that it
61
+ would be misinterpreted as a foreign-key (say for example if you named the primary key
62
+ +order_id+). In this case you can manually create the primary key as follows:
63
+
64
+ create_table :orders, :id => false do |t|
65
+ ...
66
+ t.primary_key :order_id, :references => nil
67
+ end
68
+
42
69
  The plugin fully supports and understands the following active-record
43
70
  configuration properties:
44
71
 
@@ -0,0 +1,5 @@
1
+ author: simon@redhillconsulting.com.au
2
+ summary: Automatically generates foreign-key constraints when creating tables.
3
+ homepage: http://www.redhillonrails.org
4
+ license: MIT
5
+ rails_version: EDGE
@@ -1,2 +1 @@
1
- ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, RedHillConsulting::ForeignKeyMigrations::AbstractAdapter)
2
- ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, RedHillConsulting::ForeignKeyMigrations::TableDefinition)
1
+ require 'foreign_key_migrations' unless defined?(RedHillConsulting::ForeignKeyMigrations)
@@ -0,0 +1,3 @@
1
+ ActiveRecord::Base.send(:include, RedHillConsulting::ForeignKeyMigrations::ActiveRecord::Base)
2
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, RedHillConsulting::ForeignKeyMigrations::ActiveRecord::ConnectionAdapters::AbstractAdapter)
3
+ ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, RedHillConsulting::ForeignKeyMigrations::ActiveRecord::ConnectionAdapters::TableDefinition)
@@ -0,0 +1,22 @@
1
+ module RedHillConsulting::ForeignKeyMigrations::ActiveRecord
2
+ module Base
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def references(table_name, column_name, options)
9
+ column_name = column_name.to_s
10
+ if options.has_key?(:references)
11
+ references = options[:references]
12
+ references = [references, :id] unless references.nil? || references.is_a?(Array)
13
+ references
14
+ elsif column_name == 'parent_id'
15
+ [table_name, :id]
16
+ elsif column_name =~ /^(.*)_id$/
17
+ [pluralized_table_name($1), :id]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end