backlog 0.15.1 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
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