Pratt 1.6.2 → 1.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Pratt.gemspec +38 -12
- data/README.html +85 -0
- data/README.txt +6 -3
- data/TODO +6 -3
- data/VERSION +1 -1
- data/config.rb +3 -17
- data/db/zips.csv.zip +0 -0
- data/lib/models.rb +8 -0
- data/lib/pratt.rb +58 -293
- data/lib/pratt.rb.orig +626 -0
- data/lib/pratt/core_ext.rb +6 -0
- data/lib/pratt/{array.rb → core_ext/array.rb} +5 -0
- data/lib/pratt/core_ext/float.rb +28 -0
- data/lib/pratt/core_ext/nil.rb +5 -0
- data/lib/pratt/core_ext/numeric.rb +9 -0
- data/lib/pratt/{string.rb → core_ext/string.rb} +13 -0
- data/lib/pratt/core_ext/time.rb +20 -0
- data/lib/pratt/dialogs.rb +81 -0
- data/lib/pratt/formatting.rb +24 -0
- data/lib/pratt/project_actions.rb +25 -0
- data/lib/pratt/reports.rb +127 -0
- data/models/app.rb +1 -2
- data/models/customer.rb +22 -0
- data/models/invoice.rb +28 -0
- data/models/invoice_whence.rb +18 -0
- data/models/payment.rb +1 -1
- data/models/pratt.rb +0 -9
- data/models/project.rb +16 -22
- data/models/whence.rb +10 -1
- data/models/zip.rb +27 -0
- data/spec/fixtures/graph.expectation +0 -5
- data/spec/fixtures/proportions.expectation +4 -0
- data/spec/float_spec.rb +24 -0
- data/spec/numeric_spec.rb +30 -0
- data/spec/pratt_spec.rb +5 -4
- data/spec/project_spec.rb +8 -2
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +31 -1
- data/spec/string_ext_spec.rb +33 -0
- data/views/current.eruby +5 -0
- data/views/general-invoice.eruby +538 -0
- data/views/graph.eruby +2 -7
- data/views/invoice.eruby +3 -3
- data/views/main.rb +8 -6
- data/views/proportions.eruby +4 -0
- data/views/raw.eruby +1 -1
- metadata +86 -33
- data/lib/pratt/time.rb +0 -12
- data/views/env.rb +0 -22
data/.gitignore
CHANGED
data/Pratt.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{Pratt}
|
8
|
-
s.version = "1.6.
|
8
|
+
s.version = "1.6.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Scott Noel-Hemming"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-05-30}
|
13
13
|
s.default_executable = %q{pratt.rb}
|
14
14
|
s.description = %q{
|
15
15
|
Need a way to keep track of your time, but get caught up in work? Or constant interruptions?
|
@@ -26,7 +26,8 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.email = %q{frogstarr78@gmail.com}
|
27
27
|
s.executables = ["pratt.rb"]
|
28
28
|
s.extra_rdoc_files = [
|
29
|
-
"README.
|
29
|
+
"README.html",
|
30
|
+
"README.txt",
|
30
31
|
"TODO"
|
31
32
|
]
|
32
33
|
s.files = [
|
@@ -36,6 +37,7 @@ Gem::Specification.new do |s|
|
|
36
37
|
"Manifest.txt",
|
37
38
|
"Pratt.gemspec",
|
38
39
|
"Pratt.mm",
|
40
|
+
"README.html",
|
39
41
|
"README.txt",
|
40
42
|
"Rakefile",
|
41
43
|
"Session.vim",
|
@@ -44,16 +46,30 @@ Gem::Specification.new do |s|
|
|
44
46
|
"bin/pratt.rb",
|
45
47
|
"config.rb",
|
46
48
|
"db/sqlite_databases_go_here",
|
49
|
+
"db/zips.csv.zip",
|
50
|
+
"lib/models.rb",
|
47
51
|
"lib/pratt.rb",
|
48
|
-
"lib/pratt
|
49
|
-
"lib/pratt/
|
50
|
-
"lib/pratt/
|
52
|
+
"lib/pratt.rb.orig",
|
53
|
+
"lib/pratt/core_ext.rb",
|
54
|
+
"lib/pratt/core_ext/array.rb",
|
55
|
+
"lib/pratt/core_ext/float.rb",
|
56
|
+
"lib/pratt/core_ext/nil.rb",
|
57
|
+
"lib/pratt/core_ext/numeric.rb",
|
58
|
+
"lib/pratt/core_ext/string.rb",
|
59
|
+
"lib/pratt/core_ext/time.rb",
|
60
|
+
"lib/pratt/dialogs.rb",
|
61
|
+
"lib/pratt/formatting.rb",
|
62
|
+
"lib/pratt/project_actions.rb",
|
63
|
+
"lib/pratt/reports.rb",
|
51
64
|
"models/app.rb",
|
52
65
|
"models/customer.rb",
|
66
|
+
"models/invoice.rb",
|
67
|
+
"models/invoice_whence.rb",
|
53
68
|
"models/payment.rb",
|
54
69
|
"models/pratt.rb",
|
55
70
|
"models/project.rb",
|
56
71
|
"models/whence.rb",
|
72
|
+
"models/zip.rb",
|
57
73
|
"pkgs/tile-0.8.2.tar.gz",
|
58
74
|
"pkgs/tile-0.8.2/ANNOUNCE.txt",
|
59
75
|
"pkgs/tile-0.8.2/ChangeLog",
|
@@ -298,41 +314,51 @@ Gem::Specification.new do |s|
|
|
298
314
|
"pkgs/tktray1.2.tar.gz",
|
299
315
|
"pratt.mm",
|
300
316
|
"reports/travel.log",
|
317
|
+
"reports/travel.log.2009",
|
301
318
|
"spec/app_spec.rb",
|
302
319
|
"spec/customer_spec.rb",
|
303
320
|
"spec/fixtures/graph.expectation",
|
321
|
+
"spec/fixtures/proportions.expectation",
|
322
|
+
"spec/float_spec.rb",
|
323
|
+
"spec/numeric_spec.rb",
|
304
324
|
"spec/payment_spec.rb",
|
305
325
|
"spec/pratt_spec.rb",
|
306
326
|
"spec/project_spec.rb",
|
307
327
|
"spec/rcov.opts",
|
308
328
|
"spec/spec.opts",
|
309
329
|
"spec/spec_helper.rb",
|
330
|
+
"spec/string_ext_spec.rb",
|
310
331
|
"spec/whence_spec.rb",
|
311
332
|
"tasks/pratt.rb",
|
312
333
|
"templates/model.eruby",
|
313
334
|
"templates/spec.eruby",
|
314
|
-
"views/
|
335
|
+
"views/current.eruby",
|
336
|
+
"views/general-invoice.eruby",
|
315
337
|
"views/graph.eruby",
|
316
338
|
"views/invoice.eruby",
|
317
339
|
"views/main.rb",
|
318
340
|
"views/pid.eruby",
|
319
341
|
"views/pop.rb",
|
320
342
|
"views/pop2.rb",
|
343
|
+
"views/proportions.eruby",
|
321
344
|
"views/raw.eruby"
|
322
345
|
]
|
323
346
|
s.homepage = %q{http://github.com/frogstarr78/pratt}
|
324
347
|
s.rdoc_options = ["--charset=UTF-8"]
|
325
348
|
s.require_paths = ["lib"]
|
326
349
|
s.rubyforge_project = %q{Pratt}
|
327
|
-
s.rubygems_version = %q{1.3.
|
350
|
+
s.rubygems_version = %q{1.3.6}
|
328
351
|
s.summary = %q{Pro/Re-Active Time Tracker. Track time based on what you expect to be working on, with frequent prompts to ensure accuracy.}
|
329
352
|
s.test_files = [
|
330
|
-
"spec/
|
331
|
-
"spec/project_spec.rb",
|
332
|
-
"spec/pratt_spec.rb",
|
353
|
+
"spec/whence_spec.rb",
|
333
354
|
"spec/spec_helper.rb",
|
355
|
+
"spec/float_spec.rb",
|
356
|
+
"spec/pratt_spec.rb",
|
357
|
+
"spec/project_spec.rb",
|
358
|
+
"spec/numeric_spec.rb",
|
334
359
|
"spec/app_spec.rb",
|
335
|
-
"spec/
|
360
|
+
"spec/string_ext_spec.rb",
|
361
|
+
"spec/customer_spec.rb",
|
336
362
|
"spec/payment_spec.rb"
|
337
363
|
]
|
338
364
|
|
data/README.html
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
<p>= pratt</p>
|
2
|
+
|
3
|
+
<ul>
|
4
|
+
<li>Pratt (url)</li>
|
5
|
+
</ul>
|
6
|
+
|
7
|
+
|
8
|
+
<p>== DESCRIPTION:</p>
|
9
|
+
|
10
|
+
<p>Pratt (describe your package)
|
11
|
+
(Pro/Re)-Active Time Tracker</p>
|
12
|
+
|
13
|
+
<p>== FEATURES/PROBLEMS:</p>
|
14
|
+
|
15
|
+
<p>(list of features or problems)
|
16
|
+
* Currently you'll need to manually fix the project data since I haven't
|
17
|
+
fully integrated the support for Projects to have customer's and my current
|
18
|
+
implementation is shoddy.
|
19
|
+
* Upgrading versions looses your database. (See TODO)
|
20
|
+
* Windows doesn't work (no fork). (See TODO)</p>
|
21
|
+
|
22
|
+
<p>== SYNOPSIS:</p>
|
23
|
+
|
24
|
+
<ul>
|
25
|
+
<li>pratt (code sample of usage)</li>
|
26
|
+
</ul>
|
27
|
+
|
28
|
+
|
29
|
+
<p><strong> PRATT_ENV=production pratt -D # daemonize (or if already daemonized init the
|
30
|
+
gui)
|
31
|
+
</strong> pratt -h (as you'd expect lists available commands)</p>
|
32
|
+
|
33
|
+
<p>== REQUIREMENTS:</p>
|
34
|
+
|
35
|
+
<ul>
|
36
|
+
<li>pratt
|
37
|
+
debian: libtcltk-ruby tk-tile libsqlite3-dev
|
38
|
+
gems: activerecord sqlite3-ruby rspec mocha
|
39
|
+
tk: http://sourceforge.net/project/showfiles.php?group_id=11464&package_id=107795&release_id=562098</li>
|
40
|
+
</ul>
|
41
|
+
|
42
|
+
|
43
|
+
<p>== INSTALL:</p>
|
44
|
+
|
45
|
+
<ul>
|
46
|
+
<li>sudo gem install</li>
|
47
|
+
</ul>
|
48
|
+
|
49
|
+
|
50
|
+
<p>Credits</p>
|
51
|
+
|
52
|
+
<p>Michael Goff</p>
|
53
|
+
|
54
|
+
<pre><code>Thanks for helping me with some of the workflow details
|
55
|
+
</code></pre>
|
56
|
+
|
57
|
+
<p>Michael and Kent Krenrich</p>
|
58
|
+
|
59
|
+
<pre><code>Thanks for the UI input, suggestions, and testing.
|
60
|
+
</code></pre>
|
61
|
+
|
62
|
+
<p>== LICENSE:</p>
|
63
|
+
|
64
|
+
<p>(The MIT License)</p>
|
65
|
+
|
66
|
+
<p>Copyright (c) 2009 Frogstarr78 Software</p>
|
67
|
+
|
68
|
+
<p>Permission is hereby granted, free of charge, to any person obtaining
|
69
|
+
a copy of this software and associated documentation files (the
|
70
|
+
'Software'), to deal in the Software without restriction, including
|
71
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
72
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
73
|
+
permit persons to whom the Software is furnished to do so, subject to
|
74
|
+
the following conditions:</p>
|
75
|
+
|
76
|
+
<p>The above copyright notice and this permission notice shall be
|
77
|
+
included in all copies or substantial portions of the Software.</p>
|
78
|
+
|
79
|
+
<p>THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
80
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
81
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
82
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
83
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
84
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
85
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
|
data/README.txt
CHANGED
@@ -9,10 +9,13 @@ Pratt (describe your package)
|
|
9
9
|
|
10
10
|
== FEATURES/PROBLEMS:
|
11
11
|
|
12
|
-
|
13
|
-
Currently you'll need to manually fix the project data since I haven't
|
12
|
+
(list of features or problems)
|
13
|
+
* Currently you'll need to manually fix the project data since I haven't
|
14
14
|
fully integrated the support for Projects to have customer's and my current
|
15
15
|
implementation is shoddy.
|
16
|
+
* Upgrading versions looses your database. (See TODO)
|
17
|
+
* Windows doesn't work (no fork). (See TODO)
|
18
|
+
|
16
19
|
|
17
20
|
== SYNOPSIS:
|
18
21
|
|
@@ -44,7 +47,7 @@ Michael and Kent Krenrich
|
|
44
47
|
|
45
48
|
(The MIT License)
|
46
49
|
|
47
|
-
Copyright (c) 2009
|
50
|
+
Copyright (c) 2009 Frogstarr78 Software
|
48
51
|
|
49
52
|
Permission is hereby granted, free of charge, to any person obtaining
|
50
53
|
a copy of this software and associated documentation files (the
|
data/TODO
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
General:
|
2
|
-
[ ]
|
2
|
+
[ ] Remove environment ability
|
3
3
|
[ ] Change to use raw command line arguments / Remove optparse lib
|
4
4
|
[ ] Update general package setup (It's messy)
|
5
5
|
[?] Add file watching like merb
|
6
6
|
[?] Move to Observer Pattern for reporting functionality
|
7
7
|
|
8
8
|
Invoicing:
|
9
|
-
[
|
9
|
+
[x] Add shifty week plugin
|
10
10
|
[ ] Add support for variable rates.
|
11
11
|
|
12
12
|
Templating:
|
@@ -14,8 +14,9 @@ Invoicing:
|
|
14
14
|
[ ] Move other output to template based
|
15
15
|
|
16
16
|
Data:
|
17
|
-
[
|
17
|
+
[?] Change to Use DataMapper
|
18
18
|
[?] Put everything in the db? (logs, app locks, etc)
|
19
|
+
[ ] Move database location to central location that doesn't dissappear when upgrading the app.
|
19
20
|
|
20
21
|
GUI:
|
21
22
|
[ ] Add TrayIcon.
|
@@ -23,6 +24,8 @@ GUI:
|
|
23
24
|
[ ] Payment CRUD
|
24
25
|
[ ] Re-design prompts
|
25
26
|
[ ] Remove fork in favor of ( eval OR (!?!) GUI classes )
|
27
|
+
[ ] Don't assume gui.
|
28
|
+
[ ] Add options for cli user prompting.
|
26
29
|
|
27
30
|
Test:
|
28
31
|
[ ] Add more I'm not testing everything
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.6.
|
1
|
+
1.6.4
|
data/config.rb
CHANGED
@@ -2,22 +2,13 @@ require 'active_record'
|
|
2
2
|
PRATT_ENV = ENV["PRATT_ENV"] || 'development' unless Object.const_defined? :PRATT_ENV
|
3
3
|
|
4
4
|
class Pratt
|
5
|
-
@@connected_to = nil
|
6
|
-
module Test
|
7
|
-
end
|
8
|
-
|
9
5
|
include FileUtils
|
10
6
|
|
11
7
|
class << self
|
12
|
-
def connected_to?
|
13
|
-
@@connected_to
|
14
|
-
end
|
15
|
-
|
16
8
|
def connect! to_env = :development
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
unless File.exists? connected_to?
|
9
|
+
connect_to = "db/#{to_env}.sqlite3"
|
10
|
+
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => connect_to )
|
11
|
+
unless File.exists? connect_to
|
21
12
|
Pratt.migrate
|
22
13
|
end
|
23
14
|
end
|
@@ -25,10 +16,5 @@ class Pratt
|
|
25
16
|
def connected?
|
26
17
|
ActiveRecord::Base.connected?
|
27
18
|
end
|
28
|
-
|
29
|
-
def config= env
|
30
|
-
include Pratt::Test
|
31
|
-
end
|
32
19
|
end
|
33
|
-
|
34
20
|
end
|
data/db/zips.csv.zip
ADDED
Binary file
|
data/lib/models.rb
ADDED
data/lib/pratt.rb
CHANGED
@@ -8,22 +8,18 @@ require 'colored'
|
|
8
8
|
require 'chronic'
|
9
9
|
require 'active_record'
|
10
10
|
require 'erubis'
|
11
|
-
require 'hoe'
|
12
|
-
require 'mocha'
|
13
11
|
require 'config'
|
14
12
|
require 'shifty_week'
|
15
13
|
require 'shifty_week/time'
|
16
14
|
require 'shifty_week/date'
|
17
15
|
|
18
|
-
require 'lib/pratt/
|
19
|
-
require 'lib/pratt/
|
20
|
-
require 'lib/pratt/
|
16
|
+
require 'lib/pratt/formatting'
|
17
|
+
require 'lib/pratt/core_ext'
|
18
|
+
require 'lib/pratt/dialogs'
|
19
|
+
require 'lib/pratt/project_actions'
|
20
|
+
require 'lib/pratt/reports'
|
21
|
+
require 'lib/models'
|
21
22
|
|
22
|
-
require 'models/app'
|
23
|
-
require 'models/customer'
|
24
|
-
require 'models/whence'
|
25
|
-
require 'models/project'
|
26
|
-
require 'models/payment'
|
27
23
|
|
28
24
|
class Pratt
|
29
25
|
|
@@ -49,9 +45,8 @@ class Pratt
|
|
49
45
|
PID_FILE='pratt.pid'
|
50
46
|
FMT = "%a %X %b %d %Y"
|
51
47
|
INVOICE_FMT = "%x"
|
52
|
-
@@color = true
|
53
48
|
|
54
|
-
attr_accessor :when_to, :scale, :color, :show_all, :
|
49
|
+
attr_accessor :when_to, :scale, :color, :show_all, :raw_conditions, :template, :week_day_start
|
55
50
|
attr_reader :project, :todo
|
56
51
|
def initialize proj = nil
|
57
52
|
@when_to = DateTime.now
|
@@ -61,7 +56,6 @@ class Pratt
|
|
61
56
|
@scale = nil
|
62
57
|
@show_all = false
|
63
58
|
@template = nil
|
64
|
-
@env = :development
|
65
59
|
@raw_conditions = ''
|
66
60
|
self.project = proj unless proj.nil?
|
67
61
|
end
|
@@ -82,300 +76,85 @@ class Pratt
|
|
82
76
|
@todo << what
|
83
77
|
end
|
84
78
|
|
85
|
-
#
|
86
|
-
def app
|
87
|
-
@app ||= App.last
|
88
|
-
@app
|
89
|
-
end
|
90
|
-
|
91
|
-
# TODO Rename
|
92
|
-
def graph
|
93
|
-
@primary = @off_total = @rest_total = 0.0
|
94
|
-
self.template = 'graph'
|
95
|
-
|
96
|
-
if project?
|
97
|
-
@projects = [project]
|
98
|
-
|
99
|
-
@primary = project.time_spent(scale, when_to)
|
100
|
-
@scaled_total = project.whences.time_spent(scale, when_to)
|
101
|
-
else
|
102
|
-
@projects = Project.all
|
103
|
-
|
104
|
-
@projects.each do |proj|
|
105
|
-
@primary = proj.time_spent(scale, when_to) if proj.name == Project.primary.name
|
106
|
-
@off_total = proj.time_spent(scale, when_to) if proj.name == Project.off.name
|
107
|
-
@rest_total += proj.time_spent(scale, when_to) if Project.rest.collect(&:name).include?(proj.name)
|
108
|
-
end
|
109
|
-
@scaled_total = Whence.time_spent(scale, when_to)-@off_total
|
110
|
-
end
|
111
|
-
|
112
|
-
if @primary + @off_total + @rest_total > 0.0
|
113
|
-
process_template!
|
114
|
-
else
|
115
|
-
"No data to report"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Generate an invoice for a given time period
|
120
|
-
def invoice
|
121
|
-
self.template = 'invoice'
|
122
|
-
|
123
|
-
if project?
|
124
|
-
@projects = [project]
|
125
|
-
|
126
|
-
@total = project.time_spent(scale, when_to)
|
127
|
-
else
|
128
|
-
@projects = (Project.all - [Project.primary, Project.off])
|
129
|
-
@projects.select! {|proj| show_all or ( !show_all and proj.time_spent(scale, when_to) != 0.0 ) }
|
130
|
-
|
131
|
-
@total = @projects.inject 0.0 do |total, proj|
|
132
|
-
total += proj.time_spent(scale, when_to)
|
133
|
-
total
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
@projects.each do |project|
|
138
|
-
puts "#{project.name} #{project.payment.inspect}"
|
139
|
-
end
|
140
|
-
if @total > 0.0
|
141
|
-
puts process_template!
|
142
|
-
else
|
143
|
-
puts "No data to report"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
79
|
+
# Connect to the database in irb for manual commands/investigation
|
147
80
|
def console options = []
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
def current
|
153
|
-
project_names = ([Project.primary, Project.off] | Project.rest).collect(&:name)
|
154
|
-
|
155
|
-
if last_whence = Whence.last_unended || Whence.last
|
156
|
-
puts " projects: " << (
|
157
|
-
project_names.collect {|project_name| "'#{project_name.send(last_whence.end_at.nil? && last_whence.project.name == project_name ? :green : :magenta)}'" }
|
158
|
-
) * ' '
|
159
|
-
if last_whence.end_at.nil?
|
160
|
-
puts " started: #{last_whence.start_at.strftime(FMT).send(:blue)}"
|
161
|
-
time_til = ( app.interval - ( Time.now - last_whence.start_at ) )
|
162
|
-
puts "next prompt: %s %s"% [Pratt.fmt_i( time_til / 60.0, 'min', :yellow ), Pratt.fmt_i( time_til % 60, 'sec', :yellow ) ], ''
|
163
|
-
end
|
164
|
-
else
|
165
|
-
puts " projects: " << (
|
166
|
-
project_names.collect do |project_name|
|
167
|
-
"'#{project_name.magenta}'"
|
168
|
-
end
|
169
|
-
) * ' '
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def begin
|
174
|
-
self.project.start! when_to
|
175
|
-
end
|
176
|
-
def restart
|
177
|
-
if project?
|
178
|
-
project.restart! when_to
|
179
|
-
else
|
180
|
-
Whence.last_unended.project.restart! when_to
|
181
|
-
end
|
182
|
-
end
|
183
|
-
def end
|
184
|
-
if project?
|
185
|
-
project.stop! when_to
|
186
|
-
else
|
187
|
-
Whence.last_unended.stop! when_to
|
188
|
-
end
|
189
|
-
end
|
190
|
-
def change
|
191
|
-
Whence.last.change! project.name
|
192
|
-
end
|
193
|
-
def destroy
|
194
|
-
project.destroy
|
195
|
-
end
|
196
|
-
|
197
|
-
def cpid
|
198
|
-
`pgrep -fl 'bin/pratt'`.chomp.split(' ').first
|
199
|
-
end
|
200
|
-
|
201
|
-
def pid
|
202
|
-
self.template = 'pid'
|
203
|
-
puts process_template!
|
204
|
-
end
|
205
|
-
|
206
|
-
def raw
|
207
|
-
self.template = 'raw'
|
208
|
-
|
209
|
-
if project?
|
210
|
-
@whences = project.whences.all
|
211
|
-
else
|
212
|
-
case raw_conditions
|
213
|
-
when 'all'
|
214
|
-
@whences = Whence.find raw_conditions.to_sym
|
215
|
-
when /^last$/, 'first'
|
216
|
-
@whences = [Whence.find raw_conditions.to_sym]
|
217
|
-
when /last[\(\s]?(\d+)[\)\s]?/
|
218
|
-
@whences = Whence.all.last($1.to_i)
|
219
|
-
else
|
220
|
-
@whences = Whence.all :conditions => ["start_at > ?", Chronic.parse("today 00:00")]
|
221
|
-
end
|
222
|
-
end
|
223
|
-
@whences.sort_by(&:id)
|
224
|
-
puts process_template!
|
81
|
+
require 'irb'
|
82
|
+
require 'irb/completion'
|
83
|
+
ARGV.clear
|
84
|
+
IRB.start
|
225
85
|
end
|
226
86
|
|
87
|
+
# Stop everything and kill daemonized processes.
|
227
88
|
def quit
|
228
89
|
project.stop! if project? and project.whences.last_unended
|
229
90
|
Whence.last_unended.stop! if Whence.last_unended
|
230
91
|
begin
|
231
92
|
Process.kill("KILL", app.pid.to_i)
|
232
93
|
rescue Errno::ESRCH
|
94
|
+
puts "Unable to kill Pratt@pid(#{app.pid})."
|
233
95
|
end
|
234
96
|
app.pid = ''
|
235
97
|
app.gui = ''
|
236
98
|
app.save!
|
237
99
|
end
|
238
100
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
main
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def show_env
|
248
|
-
defork { system("ruby views/env.rb ") }
|
249
|
-
end
|
250
|
-
|
251
|
-
def detect
|
252
|
-
if self.daemonized?
|
253
|
-
gui
|
254
|
-
else
|
255
|
-
daemonize!
|
256
|
-
end
|
101
|
+
# Singleton Accessor for @app
|
102
|
+
def app
|
103
|
+
@app ||= App.last
|
104
|
+
@app
|
257
105
|
end
|
258
106
|
|
107
|
+
# "Unlock" the gui.
|
259
108
|
def unlock
|
260
109
|
self.app.unlock
|
261
110
|
end
|
262
111
|
|
263
112
|
def run
|
113
|
+
# ensure we've shifted the when_to value to the
|
114
|
+
# current start of week
|
264
115
|
self.when_to.week_day_start = self.week_day_start
|
265
|
-
puts self.when_to.inspect, self.when_to.week_day_start
|
266
|
-
# must happen before any actions but after all cli argument parsing
|
267
|
-
|
268
|
-
self.begin if i_should? :begin
|
269
|
-
self.change if i_should? :change
|
270
|
-
self.restart if i_should? :restart
|
271
|
-
self.end if i_should? :end
|
272
|
-
|
273
|
-
self.destroy if i_should? :destroy
|
274
|
-
|
275
|
-
self.pid if i_should? :pid
|
276
|
-
self.raw if i_should? :raw
|
277
|
-
self.current if i_should? :current
|
278
|
-
puts self.graph if i_should? :graph
|
279
|
-
self.invoice if i_should? :invoice
|
280
|
-
self.console if i_should? :console
|
281
|
-
self.gui if i_should? :gui
|
282
|
-
self.show_env if i_should? :env
|
283
|
-
self.detect if i_should? :detect
|
284
|
-
self.unlock if i_should? :unlock
|
285
|
-
|
286
|
-
self.quit if i_should? :quit
|
287
|
-
self.daemonize! if i_should? :daemonize and not self.daemonized?
|
288
|
-
end
|
289
116
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
self.
|
117
|
+
# << order is semi important
|
118
|
+
self.end if i_should? :end
|
119
|
+
self.begin if i_should? :begin
|
120
|
+
self.change if i_should? :change
|
121
|
+
self.restart if i_should? :restart
|
122
|
+
|
123
|
+
self.destroy if i_should? :destroy
|
124
|
+
# end order is semi important
|
125
|
+
|
126
|
+
# << order doesn't matter within this set
|
127
|
+
self.pid if i_should? :pid
|
128
|
+
self.raw if i_should? :raw
|
129
|
+
self.current if i_should? :current
|
130
|
+
self.graph if i_should? :graph
|
131
|
+
self.proportions if i_should? :proportions
|
132
|
+
self.invoice if i_should? :invoice
|
133
|
+
self.console if i_should? :console
|
134
|
+
self.gui if i_should? :gui
|
135
|
+
self.detect if i_should? :detect
|
136
|
+
self.unlock if i_should? :unlock
|
137
|
+
# end order doesn't matter within this set
|
138
|
+
|
139
|
+
# << these should happen last
|
140
|
+
self.quit if i_should? :quit
|
141
|
+
self.daemonize! if i_should? :daemonize and not self.daemonized?
|
142
|
+
# end these should happen last
|
310
143
|
end
|
311
144
|
|
312
145
|
private
|
313
|
-
def main
|
314
|
-
self.app.reload
|
315
|
-
return if self.app.gui?('main', true)
|
316
|
-
self.app.log('main')
|
317
|
-
projects = ([Project.primary, Project.off] | Project.rest).collect(&:name)
|
318
|
-
if Whence.count == 0
|
319
|
-
# first run
|
320
|
-
project = Whence.new(:project => Project.primary)
|
321
|
-
else
|
322
|
-
project = Whence.last_unended || Whence.last
|
323
|
-
end
|
324
|
-
defork { system("ruby views/main.rb --projects '#{projects*"','"}' --current '#{project.project.name}'") }
|
325
|
-
end
|
326
|
-
def pop
|
327
|
-
self.app.reload
|
328
|
-
return if self.app.gui?('pop', true)
|
329
|
-
self.app.log('pop')
|
330
|
-
self.project = Whence.last_unended.project
|
331
|
-
defork { system("ruby views/pop.rb --project '#{project.name}' --start '#{project.whences.last_unended.start_at}' --project_time '#{Pratt.totals(project.time_spent)}'") }
|
332
|
-
end
|
333
|
-
|
334
146
|
def i_should? what
|
335
147
|
@todo.include?(what)
|
336
148
|
end
|
337
149
|
|
150
|
+
# Is there a project that can be operated on?
|
338
151
|
def project?
|
339
152
|
!@project.nil? and @project.name?
|
340
153
|
end
|
341
154
|
|
342
|
-
def process_template!
|
343
|
-
input = File.open(Pratt.root("views", "#{template}.eruby").first).read
|
344
|
-
erubis = Erubis::Eruby.new(input)
|
345
|
-
erubis.evaluate(self)
|
346
|
-
end
|
347
|
-
|
348
|
-
def padded_to_max string
|
349
|
-
self.class.padded_to_max string
|
350
|
-
end
|
351
|
-
|
352
|
-
def defork &block
|
353
|
-
Process.detach(
|
354
|
-
fork &block
|
355
|
-
)
|
356
|
-
end
|
357
|
-
|
358
155
|
class << self
|
359
156
|
|
360
|
-
|
361
|
-
def max
|
362
|
-
# TODO Fix me
|
363
|
-
@max ||= Project.all.inject(0) {|x,p| x = p.name.length if p.name.length > x; x }
|
364
|
-
end
|
365
|
-
|
366
|
-
def color
|
367
|
-
@@color
|
368
|
-
end
|
369
|
-
|
370
|
-
def color= c
|
371
|
-
@@color = c
|
372
|
-
end
|
373
|
-
|
374
|
-
def color?
|
375
|
-
@@color == true
|
376
|
-
end
|
377
|
-
|
378
|
-
|
157
|
+
# Parse cli arguments and init Pratt
|
379
158
|
def parse args
|
380
159
|
me = Pratt.new
|
381
160
|
|
@@ -409,6 +188,9 @@ class Pratt
|
|
409
188
|
opt.on('-I', "--invoice", "Create an invoice.") do
|
410
189
|
me << :invoice
|
411
190
|
end
|
191
|
+
opt.on('-r', '--proportions', "") do
|
192
|
+
me << :proportions
|
193
|
+
end
|
412
194
|
opt.on('-p', '--pid', "Process id display. (Is it still running)") do
|
413
195
|
me << :pid
|
414
196
|
end
|
@@ -442,7 +224,11 @@ class Pratt
|
|
442
224
|
end
|
443
225
|
|
444
226
|
# Strictly configuration options
|
445
|
-
|
227
|
+
project_names = Project.all.collect(&:name)
|
228
|
+
colored_project_names = project_names.collect{|name|
|
229
|
+
" #{name.cyan}"}
|
230
|
+
opt.on('-P', "--project PROJECT_NAME", project_names, "Set project.
|
231
|
+
Available projects are:\n#{colored_project_names*"\n"}") do |proj|
|
446
232
|
me.project = proj
|
447
233
|
end
|
448
234
|
|
@@ -485,22 +271,11 @@ class Pratt
|
|
485
271
|
opt.parse!
|
486
272
|
end
|
487
273
|
|
488
|
-
me << :env if args.include? 'env'
|
489
274
|
me << :console if args.include? 'console'
|
490
275
|
|
491
276
|
me.run
|
492
277
|
end
|
493
278
|
|
494
|
-
# Calculate totals. I think this should be an instance method on Projects/?/Whences
|
495
|
-
def totals hr, fmt = false
|
496
|
-
"#{fmt_i(hr / 24, 'day', :cyan)} #{fmt_i(hr % 24, 'hour', :yellow)} #{fmt_i((60*(hr -= hr.to_i)), 'min', :green)}"
|
497
|
-
end
|
498
|
-
|
499
|
-
def percent label, off, total, color
|
500
|
-
percent = "%0.2f"% ((off/total)*100)
|
501
|
-
padded_to_max(label) << " #{percent}%".send(color)
|
502
|
-
end
|
503
|
-
|
504
279
|
# Where is Pratt installed.
|
505
280
|
# We've already chdir'd to it's base dir in the bin file
|
506
281
|
def root *globs, &block
|
@@ -518,15 +293,10 @@ class Pratt
|
|
518
293
|
end
|
519
294
|
end
|
520
295
|
|
521
|
-
# Pad the output string to the maximum Project name
|
522
|
-
def padded_to_max string
|
523
|
-
"%#{max}.#{max}s"% string
|
524
|
-
end
|
525
|
-
|
526
296
|
# Migrate schema.
|
527
297
|
def migrate
|
528
298
|
Pratt.root( 'models', '*.rb' ) do |model_file|
|
529
|
-
klass = File.basename( model_file, '.rb' ).
|
299
|
+
klass = File.basename( model_file, '.rb' ).classify.constantize
|
530
300
|
begin
|
531
301
|
ActiveRecord::Base.connection.table_structure(model_file)
|
532
302
|
rescue ActiveRecord::StatementInvalid
|
@@ -534,10 +304,5 @@ class Pratt
|
|
534
304
|
end
|
535
305
|
end
|
536
306
|
end
|
537
|
-
|
538
|
-
def fmt_i int, label, color
|
539
|
-
"%s #{label}"% [("%02i"% int).send(color), label]
|
540
|
-
end
|
541
|
-
|
542
307
|
end
|
543
308
|
end
|