rtt 0.0.0.47 → 0.0.0.48

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,19 +3,16 @@ source 'http://gems.github.com'
3
3
 
4
4
  gem 'echoe'
5
5
  gem 'highline', '1.5.2'
6
- gem 'activesupport', ['>= 2.3.5', '<= 2.3.8']
6
+ gem 'activesupport', '3.2.6'
7
7
  gem 'prawn', '0.8.4'
8
- gem 'data_objects', '0.10.2'
9
- gem 'dm-core', '1.0.0'
10
- gem 'dm-validations', '1.0.0'
11
- gem 'dm-migrations', '1.0.0'
12
- gem 'dm-sqlite-adapter', '1.0.0'
8
+ gem 'activerecord', '3.2.6'
9
+ gem 'sqlite3'
13
10
  gem 'rake', '0.8.2'
14
11
  gem 'gemcutter', '0.7.1'
15
12
 
16
13
  group :development do
14
+ gem 'debugger'
17
15
  gem 'rspec', '1.3.0'
18
16
  gem 'mocha'
19
17
  gem 'hanna'
20
- gem 'ruby-debug'
21
18
  end
data/Gemfile.lock CHANGED
@@ -2,32 +2,32 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  remote: http://gems.github.com/
4
4
  specs:
5
- activesupport (2.3.8)
6
- addressable (2.2.7)
5
+ activemodel (3.2.6)
6
+ activesupport (= 3.2.6)
7
+ builder (~> 3.0.0)
8
+ activerecord (3.2.6)
9
+ activemodel (= 3.2.6)
10
+ activesupport (= 3.2.6)
11
+ arel (~> 3.0.2)
12
+ tzinfo (~> 0.3.29)
13
+ activesupport (3.2.6)
14
+ i18n (~> 0.6)
15
+ multi_json (~> 1.0)
7
16
  allison (2.0.3)
17
+ arel (3.0.2)
18
+ builder (3.0.0)
8
19
  columnize (0.3.6)
9
- data_objects (0.10.2)
10
- addressable (~> 2.1)
11
- dm-core (1.0.0)
12
- addressable (~> 2.1)
13
- extlib (~> 0.9.15)
14
- dm-do-adapter (1.0.0)
15
- data_objects (~> 0.10.1)
16
- dm-core (~> 1.0.0)
17
- dm-migrations (1.0.0)
18
- dm-core (~> 1.0.0)
19
- dm-sqlite-adapter (1.0.0)
20
- dm-do-adapter (~> 1.0.0)
21
- do_sqlite3 (~> 0.10.2)
22
- dm-validations (1.0.0)
23
- dm-core (~> 1.0.0)
24
- do_sqlite3 (0.10.2)
25
- data_objects (= 0.10.2)
20
+ debugger (1.2.0)
21
+ columnize (>= 0.3.1)
22
+ debugger-linecache (~> 1.1.1)
23
+ debugger-ruby_core_source (~> 1.1.3)
24
+ debugger-linecache (1.1.2)
25
+ debugger-ruby_core_source (>= 1.1.1)
26
+ debugger-ruby_core_source (1.1.3)
26
27
  echoe (4.5.6)
27
28
  allison
28
29
  gemcutter
29
30
  rubyforge
30
- extlib (0.9.15)
31
31
  gemcutter (0.7.1)
32
32
  haml (2.2.24)
33
33
  hanna (0.1.12)
@@ -35,12 +35,12 @@ GEM
35
35
  rake (~> 0.8.2)
36
36
  rdoc (~> 2.3.0)
37
37
  highline (1.5.2)
38
+ i18n (0.6.0)
38
39
  json_pure (1.6.5)
39
- linecache (0.46)
40
- rbx-require-relative (> 0.0.4)
41
40
  metaclass (0.0.1)
42
41
  mocha (0.10.4)
43
42
  metaclass (~> 0.0.1)
43
+ multi_json (1.3.6)
44
44
  prawn (0.8.4)
45
45
  prawn-core (>= 0.8.4, < 0.9)
46
46
  prawn-layout (>= 0.8.4, < 0.9)
@@ -49,27 +49,20 @@ GEM
49
49
  prawn-layout (0.8.4)
50
50
  prawn-security (0.8.4)
51
51
  rake (0.8.2)
52
- rbx-require-relative (0.0.5)
53
52
  rdoc (2.3.0)
54
53
  rspec (1.3.0)
55
- ruby-debug (0.10.4)
56
- columnize (>= 0.1)
57
- ruby-debug-base (~> 0.10.4.0)
58
- ruby-debug-base (0.10.4)
59
- linecache (>= 0.3)
60
54
  rubyforge (2.0.4)
61
55
  json_pure (>= 1.1.7)
56
+ sqlite3 (1.3.6)
57
+ tzinfo (0.3.33)
62
58
 
63
59
  PLATFORMS
64
60
  ruby
65
61
 
66
62
  DEPENDENCIES
67
- activesupport (>= 2.3.5, <= 2.3.8)
68
- data_objects (= 0.10.2)
69
- dm-core (= 1.0.0)
70
- dm-migrations (= 1.0.0)
71
- dm-sqlite-adapter (= 1.0.0)
72
- dm-validations (= 1.0.0)
63
+ activerecord (= 3.2.6)
64
+ activesupport (= 3.2.6)
65
+ debugger
73
66
  echoe
74
67
  gemcutter (= 0.7.1)
75
68
  hanna
@@ -78,4 +71,4 @@ DEPENDENCIES
78
71
  prawn (= 0.8.4)
79
72
  rake (= 0.8.2)
80
73
  rspec (= 1.3.0)
81
- ruby-debug
74
+ sqlite3
data/Manifest CHANGED
@@ -6,25 +6,25 @@ README.rdoc
6
6
  Rakefile
7
7
  USAGE.txt
8
8
  bin/rtt
9
- db/rtt.sqlite3
9
+ db/config.yml
10
+ db/schema.rb
10
11
  db/test.sqlite3
12
+ lib/extensions/array.rb
13
+ lib/extensions/date.rb
14
+ lib/extensions/hash.rb
15
+ lib/extensions/kernel.rb
16
+ lib/models/client.rb
17
+ lib/models/project.rb
18
+ lib/models/task.rb
19
+ lib/models/user.rb
11
20
  lib/rtt.rb
12
- lib/rtt/array_extensions.rb
13
21
  lib/rtt/boot.rb
14
- lib/rtt/client.rb
15
22
  lib/rtt/cmd_line_parser.rb
16
- lib/rtt/hash_extensions.rb
17
23
  lib/rtt/interactive_configurator.rb
18
- lib/rtt/project.rb
19
24
  lib/rtt/query_builder.rb
20
25
  lib/rtt/report_generator.rb
21
26
  lib/rtt/storage.rb
22
- lib/rtt/system_extensions.rb
23
- lib/rtt/task.rb
24
- lib/rtt/user.rb
25
- log/rtt.sqlite3
26
- rtt.gemspec
27
- spec/datamapper_spec_helper.rb
28
- spec/lib/rtt/task_spec.rb
27
+ spec/ar_spec_helper.rb
28
+ spec/lib/models/task_spec.rb
29
29
  spec/lib/rtt_spec.rb
30
30
  tasks/rtt.rake
data/Rakefile CHANGED
@@ -3,15 +3,15 @@ require 'echoe'
3
3
 
4
4
  # PACKAGING ============================================================
5
5
 
6
- Echoe.new('rtt', '0.0.0.47') do |p|
6
+ Echoe.new('rtt', '0.0.0.48') do |p|
7
7
  p.description = 'RTT is a tool for tracking time'
8
8
  p.url = 'http://github.com/marklazz/rtt'
9
9
  p.author = 'Marcelo Giorgi'
10
10
  p.email = 'marklazz.uy@gmail.com'
11
11
  p.ignore_pattern = [ 'tmp/*', 'script/*', '*.sh' ]
12
12
  p.runtime_dependencies = [
13
- ['highline', "1.5.2"], ['activesupport', '>= 2.3.5', '<= 2.3.8'], ['prawn', '0.8.4'], ['dm-core', '1.0.0'], [ 'dm-validations', '1.0.0'], [ 'dm-migrations', '1.0.0'], ['dm-sqlite-adapter', '1.0.0'], [ 'rake', '0.8.2' ], [ 'addressable', '2.2.7' ],
14
- [ 'allison', '2.0.3'], [ 'data_objects', '0.10.2' ], [ 'extlib', '0.9.15' ], [ 'json_pure', '1.6.5' ], [ 'prawn-core', '0.8.4' ], [ 'prawn-layout', '0.8.4'], ['prawn-security', '0.8.4'], ['haml', '2.2.24'], ['hanna', '0.1.12'], ['metaclass', '0.0.1'],
13
+ ['highline', "1.5.2"], ['activerecord', '3.2.6'], ['activesupport', '3.2.6'], ['prawn', '0.8.4'], [ 'rake', '0.8.2' ],
14
+ [ 'allison', '2.0.3'], [ 'extlib', '0.9.15' ], [ 'json_pure', '1.6.5' ], [ 'prawn-core', '0.8.4' ], [ 'prawn-layout', '0.8.4'], ['prawn-security', '0.8.4'], ['haml', '2.2.24'], ['hanna', '0.1.12'], ['metaclass', '0.0.1'],
15
15
  ['rspec', '1.3.0' ], ['mocha', '0.10.4'], ['rubyforge', '2.0.4'], ['rdoc', '2.3.0'], [ 'gemcutter', '0.7.1'], ['echoe', '4.5.6']
16
16
  ]
17
17
  p.development_dependencies = [ ]
data/bin/rtt CHANGED
@@ -2,9 +2,9 @@
2
2
  # The command line Haml parser.
3
3
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
4
4
 
5
- require 'rtt/system_extensions'
5
+ require 'extensions/kernel'
6
6
  with_warnings_suppressed do
7
- require 'rtt'
7
+ require 'rtt'
8
8
  Rtt.init
9
9
  command = Rtt.capture(ARGV)
10
10
  Rtt.execute(command)
data/db/config.yml ADDED
@@ -0,0 +1,10 @@
1
+ production:
2
+ adapter: sqlite3
3
+ database: db/production.sqlite3
4
+ pool: 5
5
+ timeout: 5000
6
+ test:
7
+ adapter: sqlite3
8
+ database: db/test.sqlite3
9
+ pool: 5
10
+ timeout: 5000
data/db/schema.rb ADDED
@@ -0,0 +1,43 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+
3
+ create_table :clients, :force => true do |t|
4
+ t.string :name, :default => Client::DEFAULT_NAME
5
+ t.string :description, :default => Client::DEFAULT_DESCRIPTION
6
+ t.boolean :active, :default => false
7
+ end
8
+
9
+ create_table :projects, :force => true do |t|
10
+ t.string :name, :default => Project::DEFAULT_NAME
11
+ t.string :description, :default => Project::DEFAULT_DESCRIPTION
12
+ t.boolean :active, :default => false
13
+ t.float :rate
14
+ t.integer :client_id
15
+ end
16
+
17
+ create_table :tasks, :force => true do |t|
18
+ t.string :name
19
+ t.date :date
20
+ t.boolean :active, :default => false
21
+ t.datetime :start_at
22
+ t.datetime :end_at
23
+ t.float :accumulated_spent_time, :default => 0
24
+ t.float :rate, :default => 0
25
+ t.integer :user_id
26
+ t.integer :project_id
27
+ end
28
+
29
+ create_table :users, :force => true do |t|
30
+ t.string :nickname
31
+ t.string :first_name
32
+ t.string :last_name
33
+ t.string :company
34
+ t.string :address
35
+ t.string :city
36
+ t.string :country
37
+ t.string :email
38
+ t.string :phone
39
+ t.string :zip
40
+ t.string :site
41
+ t.boolean :active, :default => false
42
+ end
43
+ end
data/db/test.sqlite3 CHANGED
Binary file
@@ -0,0 +1,15 @@
1
+ class Date
2
+
3
+ class << self
4
+ unless method_defined?(:day_fraction_to_time)
5
+ SECONDS_IN_DAY = Rational(1, 86400)
6
+
7
+ def day_fraction_to_time(fr)
8
+ ss, fr = fr.divmod(SECONDS_IN_DAY) # 4p
9
+ h, ss = ss.divmod(3600)
10
+ min, s = ss.divmod(60)
11
+ return h, min, s, fr
12
+ end
13
+ end
14
+ end
15
+ end
File without changes
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ class Client < ActiveRecord::Base
3
+
4
+ DEFAULT_NAME = 'default'
5
+ DEFAULT_DESCRIPTION = 'Default Client'
6
+
7
+ has_many :projects
8
+
9
+ before_create do |client|
10
+ client.active = true if Client.all.length == 0
11
+ end
12
+
13
+ def self.default
14
+ first_or_create :active => true
15
+ end
16
+
17
+ def self.current_active?
18
+ where(:active => true).first
19
+ end
20
+
21
+ def activate
22
+ deactivate_all
23
+ self.active = true
24
+ self.save
25
+ self
26
+ end
27
+
28
+ def deactivate_all
29
+ Client.all.each do |client|
30
+ client.active = false
31
+ client.save
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/ruby -w
2
+ class Project < ActiveRecord::Base
3
+
4
+ DEFAULT_NAME = 'default'
5
+ DEFAULT_DESCRIPTION = 'Default Project'
6
+
7
+ has_many :tasks
8
+ has_many :users, :through => :tasks
9
+ belongs_to :client
10
+
11
+ before_validation :set_default_client
12
+
13
+ before_create do |project|
14
+ project.active = true if Project.all.length == 0
15
+ end
16
+
17
+ def self.default
18
+ find_or_create_by_active true
19
+ end
20
+
21
+ def self.current_active?
22
+ where(:active => true).first
23
+ end
24
+
25
+ def activate
26
+ deactivate_all
27
+ self.active = true
28
+ self.save
29
+ self
30
+ end
31
+
32
+ def deactivate_all
33
+ Project.all.each do |project|
34
+ if project.id != self.id
35
+ project.active = false
36
+ project.save
37
+ end
38
+ end
39
+ end
40
+
41
+ def set_default_client
42
+ self.client = Client.default if self.client.nil?
43
+ end
44
+ end
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+ class Task < ActiveRecord::Base
3
+
4
+ DEFAULT_NAME = 'Default task'
5
+
6
+ belongs_to :project
7
+ has_one :client, :through => :project
8
+ belongs_to :user
9
+
10
+ before_validation :set_default_project
11
+ before_validation :set_default_user
12
+
13
+ def self.task(task_name)
14
+ base_attributes = { :name => task_name, :user_id => Rtt.current_user.id, :date => Date.today, :rate => (Rtt.current_project.rate if Rtt.current_project.present?) }
15
+ if task_name.nil?
16
+ existing_task = Task.where(:active => true).first
17
+ if existing_task
18
+ existing_task
19
+ else
20
+ base_attributes.merge!(:name => DEFAULT_NAME) if task_name.blank?
21
+ Task.create(base_attributes)
22
+ end
23
+ elsif (existing_task = Task.where(base_attributes).where(Task.arel_table[:start_at].gt(Date.today.beginning_of_day)).first).present?
24
+ existing_task
25
+ else
26
+ Task.create(base_attributes)
27
+ end
28
+ end
29
+
30
+ def start
31
+ self.start_at = DateTime.now
32
+ self.active = true
33
+ save
34
+ self
35
+ end
36
+
37
+ def add_current_spent_time_to_accumulated_spent_time
38
+ self.accumulated_spent_time = self.accumulated_spent_time + self.time_difference_since_start_at
39
+ end
40
+
41
+ def clone_task(task)
42
+ task = self.dup
43
+ task.id = nil
44
+ task
45
+ end
46
+
47
+ def duration
48
+ return '-' if end_at.blank?
49
+ convert_to_hour_and_minutes(accumulated_spent_time)
50
+ end
51
+
52
+ def duration=(d)
53
+ return unless !!/^(\d{1,2})[hH]{1,2}(\d{1,2})[mM]{1,2}$/.match(d)
54
+ self.start_at = DateTime.parse('00:00:01', self.date)
55
+ self.end_at = DateTime.parse('00:00:01', self.date).advance(:hours => $1.to_i, :minutes => $2.to_i, :seconds => 1)
56
+ self.accumulated_spent_time = self.time_difference_since_start_at
57
+ end
58
+
59
+ def set_default_project
60
+ self.project = Project.default if self.project.nil?
61
+ end
62
+
63
+ def set_default_user
64
+ self.user = User.default if self.user.nil?
65
+ end
66
+
67
+ def stop
68
+ split_task if span_multiple_days?
69
+ finish
70
+ self
71
+ end
72
+
73
+ def pause
74
+ split_task if span_multiple_days?
75
+ finish(DateTime.now, true)
76
+ self
77
+ end
78
+
79
+ def time_difference_since_start_at
80
+ end_date_or_now = self.end_at ? self.end_at : DateTime.now
81
+ end_date_or_now.to_datetime - self.start_at.to_datetime
82
+ end
83
+
84
+ private
85
+
86
+ def convert_to_hour_and_minutes(dif)
87
+ hours, mins = time_diff_in_hours_and_minutes(dif)
88
+ "#{hours}h#{mins}m"
89
+ end
90
+
91
+ def finish(end_at = DateTime.now, activation = false)
92
+ self.end_at = end_at
93
+ self.date = end_at.to_date
94
+ self.add_current_spent_time_to_accumulated_spent_time
95
+ self.active = activation
96
+ self.save
97
+ end
98
+
99
+ def save_in_between_days_split(date)
100
+ task = clone_task(self)
101
+ task.start_at = date.beginning_of_day
102
+ end_at = date.end_of_day.to_datetime
103
+ task.send(:finish, end_at)
104
+ task.save
105
+ end
106
+
107
+ def save_last_task_split(date)
108
+ task = clone_task(self)
109
+ end_at = date.end_of_day.to_datetime
110
+ task.send(:finish, end_at)
111
+ task.save
112
+ end
113
+
114
+ def span_multiple_days?
115
+ self.start_at.day != Date.today.day
116
+ end
117
+
118
+ def split_task
119
+ date = Date.today - 1
120
+ while (date.to_datetime > self.start_at)
121
+ save_in_between_days_split(date)
122
+ date -= 1
123
+ end
124
+ save_last_task_split(date)
125
+ self.start_at = Date.today.beginning_of_day.to_datetime
126
+ end
127
+
128
+ def time_diff_in_hours_and_minutes(dif)
129
+ Date::day_fraction_to_time(dif)
130
+ end
131
+ end