logtime 0.0.3 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77ac03824d4a2dbe1375dd8e56f22f2af21eb696
4
- data.tar.gz: 7f501f03833e8df2e86726f57d185294dabec9f8
3
+ metadata.gz: 9322d0f14a4b772705e7289e0d05d55432212dfa
4
+ data.tar.gz: 38c810feb097ec77117048e944c3e787a34843a2
5
5
  SHA512:
6
- metadata.gz: 2d47a4be6bd4297fc27b24c658cdd21a365e8e4e6023527368009a7b14c74c625126dc168bfa64a70bcebd02a266ad19d3550f6693be14edb3fa017e0ea99588
7
- data.tar.gz: 317788fe8cc68ff84d519f0c658701830a4658930d47a3c3b616b88a4613777971ea916c424aef477dd24d8da10293fb612a84fae633bd9440159fdcc4886b1d
6
+ metadata.gz: ab428f98cba504aa37ba07eaa77734aa4dcad4f73bf60bb341f084750249a0bd2c3fa8f2efefbd871a2e7bce01d2580a024ef723e4e4c6a31456b237fcbecdaa
7
+ data.tar.gz: a01dbf14f7a9a224778e70982cc10b748929ae6d1f40f7e52fde03d3028aa962e16e10efdf13ef6dfbe387a3eea759149659d20c5c3a6285cc99412571a0a9c8
checksums.yaml.gz.sig CHANGED
Binary file
data/Gemfile.lock CHANGED
@@ -16,12 +16,11 @@ GEM
16
16
  tzinfo (~> 1.1)
17
17
  arel (5.0.1.20140414130214)
18
18
  builder (3.2.2)
19
- chronic (0.10.2)
20
19
  chronic_duration (0.10.6)
21
20
  numerizer (~> 0.1.1)
22
21
  i18n (0.7.0)
23
- json (1.8.2)
24
- minitest (5.6.1)
22
+ json (1.8.3)
23
+ minitest (5.7.0)
25
24
  numerizer (0.1.1)
26
25
  sqlite3 (1.3.10)
27
26
  thor (0.19.1)
@@ -34,7 +33,6 @@ PLATFORMS
34
33
 
35
34
  DEPENDENCIES
36
35
  activerecord (~> 4.1.6)
37
- chronic (= 0.10.2)
38
36
  chronic_duration (= 0.10.6)
39
37
  sqlite3 (~> 1.3.9)
40
38
  thor (~> 0.19.1)
data/README.md CHANGED
@@ -3,30 +3,32 @@ Logtime
3
3
 
4
4
  Log your time. Get better at time estimation with statistics.
5
5
 
6
+ [![Gem Version](https://badge.fury.io/rb/logtime.svg)](https://rubygems.org/gems/logtime)
7
+
6
8
  ## Install
7
9
 
8
10
  `gem install logtime`
9
11
 
10
- ## Database
11
-
12
- The first time you run Logtime, it will take a few seconds to setup and save a new database.
13
-
14
- By default, Logtime saves a sqlite database file to `~/.logtime/database.db`.
12
+ The first time you run Logtime, it will take a few seconds to setup and save a new database; by default it saves the database file to `~/.logtime/database.db`.
15
13
 
16
14
  ## Getting help
17
15
 
18
- `logtime help` will show all commands, and `logtime help command` will tell you more about the specified command.
16
+ `lt help` will show all commands, and `lt help command` will tell you more about the specified command.
17
+
18
+ `lt add logname` **Add log**
19
19
 
20
- `logtime add logname` **Add log**
20
+ `lt add project --start false` **Add log with out starting it**
21
21
 
22
- `logtime add project --start false` **Do not start on add**
22
+ `lt add '13 James st' --tag construction,work` **Tag log**
23
23
 
24
- `logtime add 'house 5b' --tag construction,work` **Use tags**
24
+ `lt add 'new design' --estimate '2 hours and 25 minutes'` **Provide estimates**
25
25
 
26
- `logtime add 'new design' --estimate '2 hours and 25 minutes'` **Provide estimates**
26
+ `lt start name` **Start log**
27
27
 
28
- `logtime start name` **start**
28
+ `lt stop name` **Stop log**
29
29
 
30
- `logtime stop name` **stop**
30
+ `lt ls work` **List only specifically tagged logs**
31
31
 
32
+ `lt ls --order name` **List logs alphabetically**
32
33
 
34
+ `lt ls --order created_at` **List logs by create date**
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/bin/lt ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'logtime'
3
+ LogTime.start(ARGV)
@@ -1,6 +1,8 @@
1
1
  # Application configutation
2
2
  I18n.config.enforce_available_locales = true
3
- Time.zone = 'Brisbane'
4
3
  ActiveRecord::Base.default_timezone = :local
5
4
  ActiveRecord::Base.logger = Logger.new(STDERR)
6
- ActiveRecord::Base.logger.level = 1
5
+ ActiveRecord::Base.logger.level = 1
6
+
7
+ $logtime_path = File.join(File.expand_path('~'), '.logtime')
8
+ $time_display = "%Y-%m-%d %H:%M:%S"
data/config/database.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  ActiveRecord::Base.establish_connection(
2
2
  :adapter => "sqlite3",
3
- :database => File.join($config_path, 'database.db') # or otherwise ":memory:"
3
+ :database => File.join($logtime_path, 'database.db') # or otherwise ":memory:"
4
4
  )
@@ -2,7 +2,6 @@ require 'thor'
2
2
  require 'active_record'
3
3
  require 'sqlite3'
4
4
  require 'chronic_duration'
5
- $config_path = File.join(File.expand_path('~'), '.logtime')
6
- require_relative 'database.rb'
7
5
  require_relative 'application.rb'
6
+ require_relative 'database.rb'
8
7
  require_relative 'schema.rb'
data/config/schema.rb CHANGED
@@ -38,4 +38,4 @@ ActiveRecord::Schema.define do
38
38
  table.timestamps
39
39
  end unless ActiveRecord::Base.connection.table_exists? 'series'
40
40
 
41
- end unless File.exists?(File.join($config_path, 'database.db'))
41
+ end unless File.exists?(File.join($logtime_path, 'database.db'))
data/lib/commands/add.rb CHANGED
@@ -5,7 +5,7 @@ module Commands
5
5
  option :tag, :type => :string, :alias => '-t', default: ""
6
6
  option :estimate, :type => :string, :alias => '-e', default: false
7
7
  option :start, :type => :boolean, default: true
8
- desc "add [NAME]", "create new log"
8
+ desc "add [NAME]", "Create new log"
9
9
  def add(name)
10
10
  log = Log.new(name: name).tag(options[:tag])
11
11
 
@@ -28,8 +28,7 @@ module Commands
28
28
  end
29
29
 
30
30
  # start option
31
- if options[:start]
32
- log.activate if Series.begin(log_id: log.id)
31
+ if options[:start] and log.start!
33
32
  say name.to_s + " added and started", :green
34
33
  else
35
34
  say name.to_s + " added", :green
data/lib/commands/list.rb CHANGED
@@ -3,46 +3,53 @@ module Commands
3
3
  def self.included(thor)
4
4
  thor.class_eval do
5
5
  option :active, :type => :boolean, :default => true
6
- #option :tag, :type => :string, :alias => '-t'
7
- desc "ls", "list time series"
8
- def ls(tag='')
6
+ option :order, :type => :string, :default => "updated_at"
7
+ desc "ls", "List time series"
8
+ def ls(search='')
9
9
  logs = Log.where(active: options[:active]).includes(:series).includes(:tags)
10
- logs = logs.tagged(tag) if !tag.blank?
10
+ logs = logs.order(options[:order].to_sym => :desc)
11
+ logs = logs.tagged(search) if !search.blank?
11
12
 
12
13
  creep_stats = Statistics.new
13
- table = [['#', 'name', 'active', 'tags', 'series', 'time', 'estimate', 'creep %']] # header
14
+ table = [['#', 'name', '', 'tags', 'series', 'time', 'start', 'stop', 'estimate', 'creep %']] # header
14
15
  logs.each do |log|
15
16
 
16
17
  # tags
17
18
  tags = log.tags.map do |t|
18
19
  t.tag
19
20
  end
20
-
21
- # only show logs with tag, if selected
22
- # if !tag.blank?
23
- # next unless tags.include? tag
24
- # end
21
+ tags = tags.join ' '
25
22
 
26
23
  # active text
27
24
  active = "ACTIVE" if log.active == "t"
28
25
 
29
26
  # total counter
30
- total_time = (log.total/3600).round(2)
27
+ total_time = (log.total_time/3600).round(2) # to hours
28
+ total_time = "#{total_time} hours"
29
+
30
+ # first start time
31
+ start = time_display(log.series.first.start) if log.series.first
32
+
33
+ # last stop time
34
+ stop = time_display(log.series.last.end) if log.series.last
31
35
 
32
- # estimation creep
36
+ # estimation and creep
33
37
  if log.estimation
34
- creep = (total_time/log.estimation)*100
38
+ creep = log.creep # creep %
35
39
  creep_stats << creep
36
- creep = creep.round(3)
37
- estimation = (log.estimation/3600).round(3) # log estimation to hours
40
+ creep = creep.round(2) # round perecentage
41
+ estimation = (log.estimation/3600).round(2) # estimation to hours
38
42
  end
39
43
 
44
+ # table
40
45
  table << [log.id,
41
46
  log.name,
42
47
  active || '',
43
48
  tags,
44
49
  log.series.count || '',
45
50
  total_time || '',
51
+ start || '',
52
+ stop || '',
46
53
  estimation || '',
47
54
  creep || '']
48
55
  end
@@ -2,25 +2,30 @@ module Commands
2
2
  module Start
3
3
  def self.included(thor)
4
4
  thor.class_eval do
5
- desc "start [NAME]", "start new timer"
5
+ desc "start [NAME]", "Start new timer"
6
6
  def start(name)
7
+ log = Log.find_by(name: name)
7
8
 
8
9
  # not found
9
- if Log.where(name: name).count == 0
10
- say name.to_s + " not found", :red
10
+ if !log
11
+ say "#{name} not found", :red
11
12
  exit
12
13
  end
13
14
 
14
- log = Log.find_by(name: name)
15
-
16
15
  # already active?
17
- if log.active == "t"
18
- say name.to_s + " already active", :red
16
+ if log.active?
17
+ say "#{name} already active", :red
19
18
  exit
20
19
  end
21
20
 
22
21
  # begin new series, activate log
23
- series = Series.begin(log_id: log.id) and log.activate
22
+ # Series.start!(log_id: log.id)
23
+ if log.start!
24
+ started_at = time_display(Time.now)
25
+ say "#{name} started at #{started_at}", :green
26
+ else
27
+ say "#{name} failed to start", :red
28
+ end
24
29
  end
25
30
  end
26
31
  end
data/lib/commands/stop.rb CHANGED
@@ -2,25 +2,34 @@ module Commands
2
2
  module Stop
3
3
  def self.included(thor)
4
4
  thor.class_eval do
5
- desc "stop [NAME]", "stop active timer"
5
+ desc "stop [NAME]", "Stop active timer"
6
6
  def stop(name)
7
- if Log.where(name: name).count == 0
7
+ log = Log.find_by(name: name)
8
+
9
+ # not found
10
+ if !log
8
11
  say name.to_s + " not found", :red
9
12
  exit
10
13
  end
11
14
 
12
- log = Log.find_by(name: name)
13
- if log.active == "f"
14
- say name.to_s + " not active", :red
15
+ # log not active
16
+ if log.inactive?
17
+ say "#{name} not active", :red
15
18
  exit
16
19
  end
17
20
 
18
- series = log.series.last
19
- if series.stop and log.deactivate
20
- say name + " stopped!", :green
21
+ # stop log
22
+ if log.stop!
23
+ say "#{name} stopped!", :green
21
24
 
22
- # this_series = log.series.last
23
- say (series.total/3600).round(3).to_s + " hours out of " + (log.total/3600).round(3).to_s, :cyan
25
+ time_total = log.total_time/3600
26
+ time_total = time_total.round(2)
27
+ time_last = Series.find(log.series.last.id).total_time/3600
28
+ time_last = time_last.round(2)
29
+ # time_start =
30
+ say "#{time_last} hours out of #{time_total}", :cyan
31
+ else
32
+ say "#{name} failed to stop", :red
24
33
  end
25
34
  end
26
35
  end
@@ -1,5 +1,5 @@
1
1
  module TimeDisplayHelper
2
- def display_time(time)
3
- time.strftime("%H:%M:%S %d/%m/%y") if time.is_a? Time
2
+ def time_display(time)
3
+ time.strftime($time_display || "%Y-%m-%d %H:%M:%S") if time.is_a? Time
4
4
  end
5
5
  end
data/lib/models/log.rb CHANGED
@@ -10,7 +10,10 @@ class Log < ActiveRecord::Base
10
10
 
11
11
  validates :name, uniqueness: true
12
12
 
13
- has_many :series
13
+ #
14
+ # Tags
15
+ #
16
+
14
17
  has_and_belongs_to_many :tags
15
18
 
16
19
  def tag(tags)
@@ -21,27 +24,97 @@ class Log < ActiveRecord::Base
21
24
  return self
22
25
  end
23
26
 
24
- def tagged(tag)
27
+ #
28
+ # Series
29
+ #
30
+
31
+ has_many :series
32
+
33
+ #
34
+ # Stop
35
+ #
36
+
37
+ def stop
38
+ self.deactivate
39
+ self.series.last.stop!
40
+ end
25
41
 
42
+ def stop!
43
+ self.stop
44
+ self.save!
26
45
  end
27
46
 
47
+ #
48
+ # Start
49
+ #
50
+
51
+ def start(options={})
52
+ self.activate
53
+
54
+ attributes = {
55
+ start: Time.now
56
+ }.merge! options
57
+
58
+ self.series << Series.new(attributes)
59
+ end
60
+
61
+ def start!(options={})
62
+ self.start(options)
63
+ self.save!
64
+ end
65
+
66
+ #
67
+ # Activate
68
+ #
69
+
28
70
  def activate
29
71
  self.active = true
30
- self.save
31
72
  end
32
73
 
74
+ def activate!
75
+ self.activate
76
+ self.save!
77
+ end
78
+
79
+ def active?
80
+ self.active == "t"
81
+ end
82
+
83
+ #
84
+ # Deactivate
85
+ #
86
+
33
87
  def deactivate
34
88
  self.active = false
35
- self.save
36
89
  end
37
90
 
38
- def total
91
+ def deactivate!
92
+ self.active = false
93
+ self.save!
94
+ end
95
+
96
+ def inactive?
97
+ self.active == "f"
98
+ end
99
+
100
+ #
101
+ # Total time
102
+ #
103
+
104
+ def total_time
39
105
  difference = 0
40
106
  self.series.each do |s|
41
107
  ending = s.end || Time.now
42
- # next unless s.start and s.end
43
108
  difference = difference + s.start.difference(ending)
44
109
  end
45
110
  difference
46
111
  end
112
+
113
+ #
114
+ # Creep
115
+ #
116
+
117
+ def creep
118
+ self.total_time/self.estimation
119
+ end
47
120
  end
data/lib/models/series.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  class Series < ActiveRecord::Base
6
6
  belongs_to :log
7
7
 
8
- def self.begin(options = {})
8
+ def self.start!(options = {})
9
9
  attributes = {
10
10
  start: Time.now
11
11
  }.merge! options
@@ -13,12 +13,12 @@ class Series < ActiveRecord::Base
13
13
  create(attributes)
14
14
  end
15
15
 
16
- def begin
16
+ def start!
17
17
  self.start = Time.now
18
18
  self.save
19
19
  end
20
20
 
21
- def stop
21
+ def stop!
22
22
  self.end = Time.now
23
23
  self.save
24
24
  end
@@ -27,9 +27,8 @@ class Series < ActiveRecord::Base
27
27
  !self.end.blank?
28
28
  end
29
29
 
30
- def total
31
- return false if self.end.blank? or self.start.blank?
30
+ def total_time
32
31
 
33
- self.start.difference(self.end)
32
+ self.start.difference(self.end || Time.now)
34
33
  end
35
34
  end
@@ -1,6 +1,6 @@
1
1
  module SubCommands
2
2
  class Series < Thor
3
- desc "ls", "list series"
3
+ desc "ls", "List all series"
4
4
  option :order, :type => :string, :default => "updated_at"
5
5
  def ls
6
6
  series = ::Series.all.order(options[:order].to_sym => :desc)
@@ -16,13 +16,14 @@ module SubCommands
16
16
  # total time
17
17
  series_stats << timer = start.difference(finish || Time.now)
18
18
 
19
- start = display_time(start) if start
20
- finish = display_time(finish) if finish
19
+ start = time_display(start) if start
20
+ finish = time_display(finish) if finish
21
21
 
22
22
  table << [s.id,
23
- Log.find(s.log_id).name,
24
- start, finish || "active",
25
- (timer/3600).round(2).to_s] # row
23
+ s.log.name,
24
+ start,
25
+ finish || "active",
26
+ (timer/3600).round(2).to_s] # row
26
27
  end
27
28
 
28
29
  puts ''
@@ -33,27 +34,27 @@ module SubCommands
33
34
  say [(series_stats.mean/3600).round(2), " hours avg"].join(' '), :cyan
34
35
  end
35
36
 
36
- desc "rm [ID]", "remove series"
37
+ desc "rm [ID]", "Destroy series"
37
38
  option :confirm, :type => :boolean, :default => false, :alias => '-y'
38
39
  def rm(id)
39
- if ::Series.where(id: id).count == 0
40
- say "Series #" + id.to_s + " not found", :red
40
+ series = ::Series.find(id)
41
+
42
+ if !series
43
+ say "Series ##{id} not found", :red
41
44
  exit
42
45
  end
43
46
 
44
- series = ::Series.find(id)
45
-
46
47
  if !options[:confirm]
47
- say "You must --confirm before removing this series", :red
48
+ say "You must --confirm before removing series", :red
48
49
  exit
49
50
  end
50
51
 
51
52
  if !series.finished?
52
- series.log.deactivate
53
+ series.log.deactivate!
53
54
  end
54
55
 
55
56
  destroyed = series.destroy
56
- say "Series #" + id.to_s + " has been destroyed", :green
57
+ say "Series ##{id} has been destroyed", :green
57
58
  end
58
59
  end
59
60
  end
@@ -1,6 +1,6 @@
1
1
  module SubCommands
2
2
  class Tags < Thor
3
- desc "add", "create new tag"
3
+ desc "add", "Create new tag"
4
4
  def add(tag)
5
5
  tag = ::Tag.new(tag: tag.strip)
6
6
 
@@ -14,7 +14,7 @@ module SubCommands
14
14
  say tag.tag + " added!", :green
15
15
  end
16
16
 
17
- desc "rm", "remove tag"
17
+ desc "rm", "Destroy tag"
18
18
  # option :prune, :type => :boolean, :alias => '-p', :default => false not implemented yet
19
19
  def rm(tag)
20
20
  tag = ::Tag.find_by!(tag: tag)
@@ -22,7 +22,7 @@ module SubCommands
22
22
  say ["Tag", tag.tag, "destroyed forever"].join(' '), :green
23
23
  end
24
24
 
25
- desc "ls", "list all tags"
25
+ desc "ls", "List all tags"
26
26
  option :order, :type => :string, :default => "created_at"
27
27
  def ls
28
28
  tags = ::Tag.order(options[:order].to_sym => :desc)
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paperback
@@ -94,6 +94,7 @@ description: |2
94
94
  email: sam@samwhat.com
95
95
  executables:
96
96
  - logtime
97
+ - lt
97
98
  extensions: []
98
99
  extra_rdoc_files: []
99
100
  files:
@@ -104,31 +105,17 @@ files:
104
105
  - README.md
105
106
  - VERSION
106
107
  - bin/logtime
108
+ - bin/lt
107
109
  - certs/paperback.pem
108
110
  - config/application.rb
109
111
  - config/database.rb
110
112
  - config/initialisation.rb
111
113
  - config/schema.rb
112
- - lib/app/commands/add.rb
113
- - lib/app/commands/list.rb
114
- - lib/app/commands/start.rb
115
- - lib/app/commands/stop.rb
116
- - lib/app/helpers/estimate.rb
117
- - lib/app/helpers/statistics.rb
118
- - lib/app/helpers/time_to_words.rb
119
- - lib/app/logtime.rb
120
- - lib/app/models/log.rb
121
- - lib/app/models/series.rb
122
- - lib/app/models/tag.rb
123
- - lib/app/subcommands/keyword.rb
124
- - lib/app/subcommands/series.rb
125
- - lib/app/subcommands/tags.rb
126
114
  - lib/commands/add.rb
127
115
  - lib/commands/list.rb
128
116
  - lib/commands/start.rb
129
117
  - lib/commands/stop.rb
130
118
  - lib/commands/version.rb
131
- - lib/helpers/estimate.rb
132
119
  - lib/helpers/statistics.rb
133
120
  - lib/helpers/time_difference.rb
134
121
  - lib/helpers/time_display.rb
@@ -137,7 +124,6 @@ files:
137
124
  - lib/models/log.rb
138
125
  - lib/models/series.rb
139
126
  - lib/models/tag.rb
140
- - lib/subcommands/keyword.rb
141
127
  - lib/subcommands/series.rb
142
128
  - lib/subcommands/tags.rb
143
129
  - logtime.gemspec
metadata.gz.sig CHANGED
Binary file
@@ -1,41 +0,0 @@
1
- module Commands
2
- module Add
3
- def self.included(thor)
4
- thor.class_eval do
5
- option :tag, :type => :string, :alias => '-t', default: ""
6
- option :estimate, :type => :string, :alias => '-e', default: false
7
- option :start, :type => :boolean, default: true
8
- desc "add [NAME]", "create new log"
9
- def add(name)
10
- log = Log.new(name: name).tag(options[:tag])
11
-
12
- # estimate option
13
- if options[:estimate]
14
- estimation = ChronicDuration.parse(options[:estimate]) if !estimation
15
- if !estimation
16
- say "could not parse estimation time: " + options[:estimate], :red
17
- exit
18
- end
19
- log.estimation = estimation
20
- end
21
-
22
- # save log
23
- if !log.save
24
- log.errors.full_messages.each do |error|
25
- say error, :red
26
- end
27
- exit
28
- end
29
-
30
- # start option
31
- if options[:start]
32
- log.activate if Series.begin(log_id: log.id)
33
- say name.to_s + " added and started", :green
34
- else
35
- say name.to_s + " added", :green
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end