tempo-cli 0.1.6 → 0.2.1
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 +7 -0
- data/Gemfile.lock +3 -3
- data/README.md +9 -3
- data/bin/tempo +20 -2
- data/features/arrange.feature +1 -1
- data/features/directory.feature +108 -0
- data/features/project.feature +2 -2
- data/features/report.feature +3 -2
- data/features/start.feature +0 -1
- data/features/step_definitions/tempo_steps.rb +99 -20
- data/features/update.feature +7 -1
- data/lib/file_record/directory.rb +19 -3
- data/lib/file_record/file_utility.rb +122 -0
- data/lib/file_record/record.rb +36 -83
- data/lib/tempo/controllers/arrange_controller.rb +5 -5
- data/lib/tempo/controllers/base.rb +8 -8
- data/lib/tempo/controllers/checkout_controller.rb +4 -4
- data/lib/tempo/controllers/end_controller.rb +4 -5
- data/lib/tempo/controllers/projects_controller.rb +13 -10
- data/lib/tempo/controllers/records_controller.rb +8 -5
- data/lib/tempo/controllers/report_controller.rb +4 -4
- data/lib/tempo/controllers/start_controller.rb +4 -3
- data/lib/tempo/controllers/update_controller.rb +22 -8
- data/lib/tempo/exceptions.rb +2 -2
- data/lib/tempo/models/base.rb +26 -18
- data/lib/tempo/models/composite.rb +5 -3
- data/lib/tempo/models/log.rb +61 -38
- data/lib/tempo/models/project.rb +9 -6
- data/lib/tempo/models/time_record.rb +14 -14
- data/lib/tempo/version.rb +1 -1
- data/lib/tempo/views/arrange_view.rb +4 -4
- data/lib/tempo/views/base.rb +10 -23
- data/lib/tempo/views/formatters/base.rb +2 -2
- data/lib/tempo/views/formatters/screen.rb +7 -7
- data/lib/tempo/views/projects_view.rb +8 -8
- data/lib/tempo/views/report_view.rb +5 -5
- data/lib/tempo/views/reporter.rb +4 -4
- data/lib/tempo/views/time_record_view.rb +5 -5
- data/lib/tempo/views/view_records/base.rb +8 -8
- data/lib/tempo/views/view_records/composite.rb +4 -4
- data/lib/tempo/views/view_records/log.rb +3 -3
- data/lib/tempo/views/view_records/project.rb +3 -3
- data/lib/tempo/views/view_records/time_record.rb +5 -5
- data/lib/tempo.rb +3 -0
- data/lib/time_utilities.rb +4 -4
- data/tempo-cli.gemspec +8 -7
- data/test/lib/file_record/directory_test.rb +14 -1
- data/test/lib/file_record/record_test.rb +40 -75
- data/test/lib/tempo/models/base_test.rb +2 -2
- data/test/lib/tempo/models/composite_test.rb +9 -9
- data/test/lib/tempo/models/log_test.rb +31 -16
- data/test/lib/tempo/models/time_record_test.rb +29 -19
- data/test/support/factories.rb +5 -0
- data/test/support/helpers.rb +7 -7
- metadata +40 -53
data/lib/file_record/record.rb
CHANGED
@@ -1,65 +1,20 @@
|
|
1
|
+
# Handles the CRUD of base, composite and log models
|
2
|
+
# relies on file utility to manage the directories and filenames.
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
|
1
6
|
module FileRecord
|
2
7
|
class Record
|
3
8
|
class << self
|
4
9
|
|
5
|
-
# record
|
6
|
-
|
7
|
-
# @options file file path to record to
|
8
|
-
# @options record string or object to record
|
9
|
-
# options
|
10
|
-
# - force: true, overwrite file
|
11
|
-
# - format: 'yaml', 'string'
|
12
|
-
def create( file, record, options={} )
|
13
|
-
|
14
|
-
if record.is_a?(String)
|
15
|
-
format = options.fetch(:format, 'string')
|
16
|
-
else
|
17
|
-
format = options.fetch(:format, 'yaml')
|
18
|
-
end
|
19
|
-
|
20
|
-
if File.exists?(file)
|
21
|
-
raise ArgumentError.new "file already exists" unless options[:force]
|
22
|
-
end
|
23
|
-
|
24
|
-
File.open( file,'w' ) do |f|
|
25
|
-
|
26
|
-
case format
|
27
|
-
when 'yaml'
|
28
|
-
f.puts YAML::dump( record )
|
29
|
-
when 'string'
|
30
|
-
f.puts record
|
31
|
-
else
|
32
|
-
f.puts record
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def log_dirname( model )
|
38
|
-
dir_name = model.name[14..-1].gsub(/([A-Z])/, '_\1').downcase
|
39
|
-
dir = "tempo#{dir_name}s"
|
40
|
-
end
|
41
|
-
|
42
|
-
def log_dir( model )
|
43
|
-
dir_name = log_dirname model
|
44
|
-
dir = File.join(Dir.home,'tempo', dir_name)
|
45
|
-
Dir.mkdir(dir, 0700) unless File.exists?(dir)
|
46
|
-
dir
|
47
|
-
end
|
48
|
-
|
49
|
-
def log_filename( model, time )
|
50
|
-
file = "#{model.day_id( time )}.yaml"
|
51
|
-
end
|
10
|
+
# record a child of Tempo::Model::Base
|
11
|
+
def save_model( model, options={} )
|
52
12
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
13
|
+
options = options.dup
|
14
|
+
options[:create] = true
|
15
|
+
options[:destroy] = true
|
57
16
|
|
58
|
-
|
59
|
-
def save_model( model )
|
60
|
-
file = model_filename model
|
61
|
-
file_path = File.join(Dir.home,'tempo', file)
|
62
|
-
File.delete( file_path ) if File.exists?( file_path )
|
17
|
+
file_path = FileUtility.new(model, options).file_path
|
63
18
|
|
64
19
|
File.open( file_path,'a' ) do |f|
|
65
20
|
model.index.each do |m|
|
@@ -69,52 +24,50 @@ module FileRecord
|
|
69
24
|
end
|
70
25
|
|
71
26
|
# record a child of Tempo::Model::Log
|
72
|
-
def save_log( model )
|
73
|
-
|
27
|
+
def save_log( model, options={} )
|
28
|
+
|
29
|
+
options = options.dup
|
30
|
+
options[:create] = true
|
31
|
+
options[:destroy] = true
|
74
32
|
|
75
33
|
model.days_index.each do |day, days_logs|
|
76
|
-
file = "#{day.to_s}.yaml"
|
77
|
-
file_path = File.join(dir, file)
|
78
|
-
File.delete( file_path ) if File.exists?( file_path )
|
79
34
|
|
80
|
-
|
35
|
+
options[:time] = day
|
36
|
+
ut = FileUtility.new(model, options)
|
37
|
+
|
38
|
+
# don't create an empty file
|
81
39
|
next if days_logs.empty?
|
82
40
|
|
83
|
-
|
84
|
-
days_logs.each do |log|
|
85
|
-
f.puts YAML::dump( log.freeze_dry )
|
86
|
-
end
|
87
|
-
end
|
41
|
+
ut.save_instances_to_file days_logs
|
88
42
|
end
|
89
43
|
end
|
90
44
|
|
91
|
-
|
45
|
+
# Used by read_model and read_log to load all instances from a file
|
46
|
+
#
|
47
|
+
def read_instances( model, file, options={} )
|
92
48
|
instances = YAML::load_stream( File.open( file ) )
|
93
49
|
instances.each do |i|
|
94
50
|
model.new( i )
|
95
51
|
end
|
96
52
|
end
|
97
53
|
|
98
|
-
|
99
|
-
|
100
|
-
read_instances model, file
|
101
|
-
end
|
54
|
+
# Read in all models instances from the model file
|
55
|
+
def read_model( model, options={} )
|
102
56
|
|
103
|
-
|
104
|
-
|
105
|
-
file = File.join(dir, model.file( time ))
|
106
|
-
if File.exists? file
|
107
|
-
read_instances model, file
|
108
|
-
end
|
57
|
+
file_path = FileUtility.new(model, options).file_path
|
58
|
+
read_instances model, file_path
|
109
59
|
end
|
110
|
-
end
|
111
60
|
|
112
|
-
|
61
|
+
# Read in all log model instances from a time stamped file
|
62
|
+
def read_log( model, time, options={} )
|
113
63
|
|
114
|
-
|
115
|
-
|
116
|
-
def delete
|
64
|
+
options[:time] = time
|
65
|
+
file_path = FileUtility.new(model, options).file_path
|
117
66
|
|
67
|
+
if File.exists? file_path
|
68
|
+
read_instances model, file_path
|
69
|
+
end
|
70
|
+
end
|
118
71
|
end
|
119
72
|
end
|
120
73
|
end
|
@@ -5,7 +5,7 @@ module Tempo
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
|
8
|
-
def parse
|
8
|
+
def parse(options, args)
|
9
9
|
|
10
10
|
return Views.project_assistance if Model::Project.index.empty?
|
11
11
|
|
@@ -29,23 +29,23 @@ module Tempo
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def make_root_project
|
32
|
+
def make_root_project(options, args)
|
33
33
|
root = match_project :arrange, options, args
|
34
34
|
if root.parent == :root
|
35
35
|
Views::arrange_already_root root
|
36
36
|
else
|
37
37
|
parent = match_project :arrange, {id: true}, root.parent
|
38
38
|
parent.remove_child root
|
39
|
-
@projects.save_to_file
|
39
|
+
@projects.save_to_file options
|
40
40
|
Views::arrange_root root
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def make_child_project
|
44
|
+
def make_child_project(options, parent_args, child_args)
|
45
45
|
parent = match_project :arrange, options, parent_args
|
46
46
|
child = match_project :arrange, options, child_args
|
47
47
|
parent << child
|
48
|
-
@projects.save_to_file
|
48
|
+
@projects.save_to_file options
|
49
49
|
Views::arrange_parent_child parent, child
|
50
50
|
end
|
51
51
|
end #class << self
|
@@ -3,7 +3,7 @@ module Tempo
|
|
3
3
|
class Base
|
4
4
|
class << self
|
5
5
|
|
6
|
-
def filter_projects_by_title
|
6
|
+
def filter_projects_by_title(options, args)
|
7
7
|
if options[:exact]
|
8
8
|
match = reassemble_the args
|
9
9
|
match = [match]
|
@@ -18,7 +18,7 @@ module Tempo
|
|
18
18
|
# that match positively against every
|
19
19
|
# member of the matches array
|
20
20
|
#
|
21
|
-
def fuzzy_match
|
21
|
+
def fuzzy_match(haystack, matches, attribute="id")
|
22
22
|
|
23
23
|
matches = [matches] unless matches.is_a? Array
|
24
24
|
|
@@ -38,7 +38,7 @@ module Tempo
|
|
38
38
|
# a flag in the front. The value is also added back intto the
|
39
39
|
# front of the original array
|
40
40
|
|
41
|
-
def reassemble_the
|
41
|
+
def reassemble_the(args, flag=nil)
|
42
42
|
assembled = ""
|
43
43
|
args.unshift flag if flag
|
44
44
|
args.each { |a| assembled += " #{a}" }
|
@@ -48,7 +48,7 @@ module Tempo
|
|
48
48
|
private
|
49
49
|
|
50
50
|
# TODO: escape regex characters ., (), etc.
|
51
|
-
def match_to_regex
|
51
|
+
def match_to_regex(match, type=:fuzzy)
|
52
52
|
match.downcase!
|
53
53
|
if type == :exact
|
54
54
|
/^#{match}$/
|
@@ -57,7 +57,7 @@ module Tempo
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
def fuzzy_array_match
|
60
|
+
def fuzzy_array_match(haystack, matches)
|
61
61
|
results = []
|
62
62
|
matches.each do |m|
|
63
63
|
reg = match_to_regex m
|
@@ -70,7 +70,7 @@ module Tempo
|
|
70
70
|
haystack
|
71
71
|
end
|
72
72
|
|
73
|
-
def model_match
|
73
|
+
def model_match(haystack, matches, attribute, type=:fuzzy)
|
74
74
|
attribute = "@#{attribute}".to_sym
|
75
75
|
contenders = haystack.index
|
76
76
|
results = []
|
@@ -85,7 +85,7 @@ module Tempo
|
|
85
85
|
contenders
|
86
86
|
end
|
87
87
|
|
88
|
-
def match_project
|
88
|
+
def match_project(command, options, args)
|
89
89
|
if options[:id]
|
90
90
|
match = @projects.find_by_id args[0]
|
91
91
|
Views::no_match_error( "projects", "id=#{args[0]}" ) if not match
|
@@ -99,7 +99,7 @@ module Tempo
|
|
99
99
|
|
100
100
|
# verify one and only one match returned in match array
|
101
101
|
# returns the single match
|
102
|
-
def single_match
|
102
|
+
def single_match(matches, request, command)
|
103
103
|
|
104
104
|
if matches.length == 0
|
105
105
|
Views::no_match_error "projects", request
|
@@ -5,7 +5,7 @@ module Tempo
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
|
8
|
-
def add_project
|
8
|
+
def add_project(options, args)
|
9
9
|
request = reassemble_the args, options[:add]
|
10
10
|
|
11
11
|
if @projects.include? request
|
@@ -13,12 +13,12 @@ module Tempo
|
|
13
13
|
|
14
14
|
else
|
15
15
|
project = @projects.new({ title: request, current: true })
|
16
|
-
@projects.save_to_file
|
16
|
+
@projects.save_to_file options
|
17
17
|
Views::project_checkout project
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def existing_project
|
21
|
+
def existing_project(options, args)
|
22
22
|
|
23
23
|
match = match_project :checkout, options, args
|
24
24
|
|
@@ -27,7 +27,7 @@ module Tempo
|
|
27
27
|
Views::project_already_current match
|
28
28
|
else
|
29
29
|
@projects.current = match
|
30
|
-
@projects.save_to_file
|
30
|
+
@projects.save_to_file options
|
31
31
|
Views::project_checkout match
|
32
32
|
end
|
33
33
|
end
|
@@ -8,7 +8,7 @@ module Tempo
|
|
8
8
|
|
9
9
|
class << self
|
10
10
|
|
11
|
-
def end_timer
|
11
|
+
def end_timer(options, args)
|
12
12
|
|
13
13
|
return Views.project_assistance if Model::Project.index.empty?
|
14
14
|
|
@@ -20,17 +20,16 @@ module Tempo
|
|
20
20
|
|
21
21
|
return Views.no_match_error( "valid timeframe", options[:at], false ) if not time_out
|
22
22
|
|
23
|
-
options =
|
23
|
+
options[:end_time] = time_out
|
24
24
|
options[:description] = reassemble_the args
|
25
25
|
|
26
|
-
@time_records.load_last_day
|
26
|
+
@time_records.load_last_day options
|
27
27
|
record = @time_records.current
|
28
|
-
|
29
28
|
return Views.no_items( "running time records", :error ) if ! record
|
30
29
|
|
31
30
|
record.end_time = time_out
|
32
31
|
record.description = options[:description] if options[:description]
|
33
|
-
@time_records.save_to_file
|
32
|
+
@time_records.save_to_file options
|
34
33
|
|
35
34
|
Views.end_time_record_view record
|
36
35
|
|
@@ -5,13 +5,16 @@ module Tempo
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
|
8
|
-
def load
|
9
|
-
|
10
|
-
|
8
|
+
def load(options={})
|
9
|
+
|
10
|
+
directory = options.fetch( :directory, ENV['HOME'])
|
11
|
+
|
12
|
+
if File.exists?( File.join( directory, 'tempo', @projects.file ))
|
13
|
+
@projects.read_from_file options
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
14
|
-
def index
|
17
|
+
def index(options, args)
|
15
18
|
|
16
19
|
request = reassemble_the args
|
17
20
|
|
@@ -39,7 +42,7 @@ module Tempo
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
|
-
def add
|
45
|
+
def add(options, args, tags=nil)
|
43
46
|
request = reassemble_the args
|
44
47
|
|
45
48
|
if @projects.include? request
|
@@ -52,13 +55,13 @@ module Tempo
|
|
52
55
|
@projects.current = project
|
53
56
|
end
|
54
57
|
|
55
|
-
@projects.save_to_file
|
58
|
+
@projects.save_to_file options
|
56
59
|
|
57
60
|
Views::project_added project
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|
61
|
-
def delete
|
64
|
+
def delete(options, args)
|
62
65
|
|
63
66
|
reassemble_the args, options[:delete]
|
64
67
|
match = match_project :delete, options, args
|
@@ -70,7 +73,7 @@ module Tempo
|
|
70
73
|
|
71
74
|
if @projects.index.include?(match)
|
72
75
|
match.delete
|
73
|
-
@projects.save_to_file
|
76
|
+
@projects.save_to_file options
|
74
77
|
Views::projects_list_view if options[:list]
|
75
78
|
Views::project_deleted match
|
76
79
|
end
|
@@ -78,7 +81,7 @@ module Tempo
|
|
78
81
|
end
|
79
82
|
|
80
83
|
# add a project with tags, or tag or untag an existing project
|
81
|
-
def tag
|
84
|
+
def tag(options, args)
|
82
85
|
|
83
86
|
# TODO @projects_find_by_tag if args.empty?
|
84
87
|
|
@@ -96,7 +99,7 @@ module Tempo
|
|
96
99
|
if match
|
97
100
|
match.tag tags
|
98
101
|
match.untag untags
|
99
|
-
@projects.save_to_file
|
102
|
+
@projects.save_to_file options
|
100
103
|
Views::project_tags match
|
101
104
|
end
|
102
105
|
end
|
@@ -5,17 +5,20 @@ module Tempo
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
|
8
|
-
def initialize_from_records
|
9
|
-
if File.exists?( File.join( ENV['HOME'], 'tempo' ))
|
8
|
+
def initialize_from_records(options, args)
|
10
9
|
|
11
|
-
|
10
|
+
dir = File.join( options.fetch( :directory, ENV['HOME']))
|
11
|
+
|
12
|
+
if File.exists?(File.join(dir, 'tempo'))
|
13
|
+
|
14
|
+
Tempo::Controllers::Projects.load directory: dir
|
12
15
|
|
13
16
|
else
|
14
|
-
FileRecord::Directory.create_new
|
17
|
+
FileRecord::Directory.create_new directory: dir
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
21
|
end #class << self
|
19
22
|
end
|
20
23
|
end
|
21
|
-
end
|
24
|
+
end
|
@@ -6,7 +6,7 @@ module Tempo
|
|
6
6
|
|
7
7
|
class << self
|
8
8
|
|
9
|
-
def report
|
9
|
+
def report(options, args)
|
10
10
|
|
11
11
|
return Tempo::Views.project_assistance if Tempo::Model::Project.index.empty?
|
12
12
|
|
@@ -21,7 +21,7 @@ module Tempo
|
|
21
21
|
to = Time.parse options[:to]
|
22
22
|
return Views.no_match_error( "valid timeframe", options[:to], false ) if to.nil?
|
23
23
|
|
24
|
-
@time_records.load_days_records from, to
|
24
|
+
@time_records.load_days_records from, to, options
|
25
25
|
|
26
26
|
error_timeframe = " from #{from.strftime('%m/%d/%Y')} to #{to.strftime('%m/%d/%Y')}"
|
27
27
|
|
@@ -29,7 +29,7 @@ module Tempo
|
|
29
29
|
# current day record
|
30
30
|
#
|
31
31
|
elsif args.empty?
|
32
|
-
@time_records.load_last_day
|
32
|
+
@time_records.load_last_day options
|
33
33
|
|
34
34
|
# arguments have been supplied,
|
35
35
|
# so we return the records for a single day
|
@@ -40,7 +40,7 @@ module Tempo
|
|
40
40
|
day = Time.parse time
|
41
41
|
return Views.no_match_error( "valid timeframe", time, false ) if day.nil?
|
42
42
|
|
43
|
-
@time_records.load_day_record day
|
43
|
+
@time_records.load_day_record day, options
|
44
44
|
|
45
45
|
error_timeframe = " on #{day.strftime('%m/%d/%Y')}"
|
46
46
|
end
|
@@ -8,7 +8,7 @@ module Tempo
|
|
8
8
|
|
9
9
|
class << self
|
10
10
|
|
11
|
-
def start_timer
|
11
|
+
def start_timer(options, args)
|
12
12
|
|
13
13
|
return Views.project_assistance if Model::Project.index.empty?
|
14
14
|
|
@@ -28,9 +28,10 @@ module Tempo
|
|
28
28
|
return Views.no_match_error( "valid timeframe", options[:end], false ) if time_out.nil?
|
29
29
|
opts[:end_time] = time_out
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
|
+
@time_records.load_last_day options
|
32
33
|
record = @time_records.new(opts)
|
33
|
-
@time_records.save_to_file
|
34
|
+
@time_records.save_to_file options
|
34
35
|
|
35
36
|
Views.start_time_record_view record
|
36
37
|
|
@@ -8,20 +8,22 @@ module Tempo
|
|
8
8
|
|
9
9
|
class << self
|
10
10
|
|
11
|
-
def parse
|
11
|
+
def parse(options, args)
|
12
12
|
|
13
13
|
reassemble_the args
|
14
14
|
|
15
15
|
return Views.project_assistance if Model::Project.index.empty?
|
16
16
|
|
17
|
+
# Load last day, or specific day if options includes an on-date
|
17
18
|
if options[:on]
|
18
19
|
day = Time.parse options[:on]
|
19
20
|
return Views.no_match_error( "valid timeframe", options[:from], false ) if day.nil?
|
20
|
-
@time_records.load_day_record day
|
21
|
+
@time_records.load_day_record day, options
|
21
22
|
else
|
22
|
-
day = @time_records.load_last_day
|
23
|
+
day = @time_records.load_last_day options
|
23
24
|
end
|
24
25
|
|
26
|
+
# Load the last record, or record by id if options includes an id
|
25
27
|
if options[:id]
|
26
28
|
record = @time_records.find_by_id( options[:id], day )
|
27
29
|
return Views.no_match_error( "time record on #{day.strftime('%m/%d/%Y')}", "id = #{options[:id]}", false ) if !record
|
@@ -30,13 +32,22 @@ module Tempo
|
|
30
32
|
return Views.no_items( "time records on #{day.strftime('%m/%d/%Y')}", :error ) if ! record
|
31
33
|
end
|
32
34
|
|
33
|
-
|
35
|
+
# DELETE and existing record, no need to check for further updates
|
34
36
|
if options[:delete]
|
35
|
-
|
36
|
-
|
37
|
+
|
38
|
+
# If only record on the given day, delete the file
|
39
|
+
if Tempo::Model::TimeRecord.ids(record.d_id).length == 1
|
40
|
+
@time_records.delete_day_record record.d_id, options
|
41
|
+
else
|
42
|
+
record.delete
|
43
|
+
@time_records.save_to_file options
|
44
|
+
end
|
45
|
+
|
37
46
|
Views.delete_time_record_view record
|
38
47
|
|
39
|
-
else
|
48
|
+
else # check for flags and update one or all attributes
|
49
|
+
|
50
|
+
# Update the START time of the record
|
40
51
|
if options[:start]
|
41
52
|
start_time = Time.parse options[:start]
|
42
53
|
return Views.no_match_error( "valid timeframe", options[:at], false ) if start_time.nil?
|
@@ -49,6 +60,7 @@ module Tempo
|
|
49
60
|
end
|
50
61
|
end
|
51
62
|
|
63
|
+
# Update the END time of the record
|
52
64
|
if options[:end]
|
53
65
|
end_time = Time.parse options[:end]
|
54
66
|
return Views.no_match_error( "valid timeframe", options[:at], false ) if end_time.nil?
|
@@ -61,14 +73,16 @@ module Tempo
|
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
76
|
+
# Update the PROJECT
|
64
77
|
if options[:project]
|
65
78
|
record.project = @projects.current.id
|
66
79
|
end
|
67
80
|
|
81
|
+
# Update the DESCRIPTION
|
68
82
|
options[:description] = reassemble_the args
|
69
83
|
record.description = options[:description] if options[:description] && !options[:description].empty?
|
70
84
|
|
71
|
-
@time_records.save_to_file
|
85
|
+
@time_records.save_to_file options
|
72
86
|
Views.update_time_record_view record
|
73
87
|
end
|
74
88
|
end
|
data/lib/tempo/exceptions.rb
CHANGED
@@ -19,7 +19,7 @@ module Tempo
|
|
19
19
|
#
|
20
20
|
class TimeConflictError < ArgumentError
|
21
21
|
|
22
|
-
def initialize(
|
22
|
+
def initialize(start_time=nil, end_time=nil, target_start_time=nil, target_end_time=nil)
|
23
23
|
|
24
24
|
@end_time = (end_time.kind_of? Time) ? end_time.strftime('%H:%M') : end_time.to_s
|
25
25
|
@end_time = " - #{@end_time}" if !@end_time.empty?
|
@@ -36,4 +36,4 @@ module Tempo
|
|
36
36
|
@message
|
37
37
|
end
|
38
38
|
end
|
39
|
-
end
|
39
|
+
end
|