wlog 1.0.0 → 1.0.5
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 +4 -4
- data/.rspec +1 -0
- data/README.md +57 -9
- data/Rakefile +24 -0
- data/bin/wlog +10 -0
- data/lib/wlog/commands/archive_finished_issues.rb +20 -0
- data/lib/wlog/commands/archive_issues.rb +22 -0
- data/lib/wlog/commands/concat_description.rb +8 -2
- data/lib/wlog/commands/delete_issue.rb +31 -0
- data/lib/wlog/commands/innit_db.rb +0 -2
- data/lib/wlog/commands/make_csv.rb +7 -1
- data/lib/wlog/commands/new_entry.rb +7 -2
- data/lib/wlog/commands/replace_pattern.rb +4 -6
- data/lib/wlog/commands/taint_setup.rb +18 -0
- data/lib/wlog/db_registry.rb +3 -5
- data/lib/wlog/domain.rb +13 -0
- data/lib/wlog/domain/attachment.rb +25 -17
- data/lib/wlog/domain/helpers.rb +4 -0
- data/lib/wlog/domain/issue.rb +77 -23
- data/lib/wlog/domain/key_value.rb +21 -17
- data/lib/wlog/domain/log_entry.rb +35 -21
- data/lib/wlog/domain/session.rb +17 -0
- data/lib/wlog/domain/sql_modules/issue_sql.rb +13 -5
- data/lib/wlog/domain/static_configurations.rb +9 -0
- data/lib/wlog/domain/sys_config.rb +76 -6
- data/lib/wlog/domain/template_engine.rb +55 -0
- data/lib/wlog/domain/timelog_helper.rb +53 -0
- data/lib/wlog/sql/seq/2.sql +4 -0
- data/lib/wlog/{domain → tech}/ansi_colors.rb +7 -6
- data/lib/wlog/tech/uncolored_string.rb +14 -0
- data/lib/wlog/tech/wlog_string.rb +23 -0
- data/lib/wlog/ui/bootstrap.rb +18 -0
- data/lib/wlog/ui/cli_interface.rb +94 -34
- data/lib/wlog/ui/commands/create_issue.rb +8 -4
- data/lib/wlog/ui/issue_ui.rb +47 -41
- data/lib/wlog/ui/setup_wizard.rb +34 -0
- data/lib/wlog/version.rb +1 -1
- data/spec/domain/attachment_spec.rb +59 -0
- data/spec/domain/commands/concat_desc_spec.rb +51 -0
- data/spec/domain/commands/new_entry_spec.rb +41 -0
- data/spec/domain/commands/replace_pattern_spec.rb +46 -0
- data/spec/domain/issue_spec.rb +127 -0
- data/spec/domain/key_value_spec.rb +42 -0
- data/spec/domain/log_entry_spec.rb +85 -0
- data/spec/domain/sys_config_spec.rb +38 -0
- data/spec/make_db.rb +8 -0
- data/spec/old-databases/README.md +6 -0
- data/spec/old-databases/default +0 -0
- data/spec/tech/uncolored_string.rb +20 -0
- data/spec/tech/wlog_string_spec.rb +46 -0
- data/wlog.gemspec +5 -3
- metadata +44 -6
- data/spec/key_vale_spec.rb +0 -9
@@ -0,0 +1,55 @@
|
|
1
|
+
module Wlog
|
2
|
+
# A very simple templating engine that supports generating text files in order
|
3
|
+
# for them to be, in turn parsed by some other tool in order to generate nice
|
4
|
+
# invoices. The 'other' tool I have in mind is pandoc; this somewhat defeats
|
5
|
+
# the purpose of 'lightweight' in the sense that we indirectly need that tool,
|
6
|
+
# but on the other hand writing a more complex templating engine might prove
|
7
|
+
# too costly for now.
|
8
|
+
#
|
9
|
+
# @author Simon Symeonidis
|
10
|
+
class TemplateEngine
|
11
|
+
|
12
|
+
# These can either be atomic elements, or arrays of two. In the former, they
|
13
|
+
# just join entries by adding the separator. The latter makes the two a
|
14
|
+
# prefix, and postfix.
|
15
|
+
# @param issue_sep is what to separate issues with
|
16
|
+
# @param log_entry_sep is what to separate log entries with
|
17
|
+
def initialize(issue_sep, log_entry_sep, issues, invoice_id)
|
18
|
+
@issue_sep, @log_entry_sep, @issues, @invoice_id = \
|
19
|
+
issue_sep, log_entry_sep, issues, invoice_id
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate(filename)
|
23
|
+
contents = File.open(filename).read
|
24
|
+
contens.gsub(InvoiceId, @invoice_id)
|
25
|
+
end
|
26
|
+
|
27
|
+
# What to separate issues with
|
28
|
+
attr_accessor :issue_sep
|
29
|
+
|
30
|
+
# What to separate log entries with
|
31
|
+
attr_accessor :log_entry_sep
|
32
|
+
|
33
|
+
# An issue list
|
34
|
+
attr_accessor :issues
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# The tag to look for in order to add the issue info
|
39
|
+
IssueTag = '<issue-sep>'
|
40
|
+
|
41
|
+
# The log entry tag to add the log entries
|
42
|
+
LogEntrySep = '<log-entry-sep>'
|
43
|
+
|
44
|
+
InvoiceId = '<id>'
|
45
|
+
|
46
|
+
DateFrom = '<date-from>'
|
47
|
+
|
48
|
+
DateTo = '<date-to>'
|
49
|
+
|
50
|
+
StartSegment = '[segment]'
|
51
|
+
EndSegment = '[/segment]'
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Wlog
|
2
|
+
# Helper class that reads in a string in the form of eg: 4h20m and should be
|
3
|
+
# able to extract time in seconds.
|
4
|
+
# @author Simon Symeonidis
|
5
|
+
class TimelogHelper
|
6
|
+
# Parse a timelog string
|
7
|
+
def self.parse(str)
|
8
|
+
loggings = str.scan(/\d+[A-Za-z]/)
|
9
|
+
self.calculate_time(loggings)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param time is time in seconds
|
13
|
+
# @return in nice format (2d 1h 20m)
|
14
|
+
def self.time_to_s(time)
|
15
|
+
str = ""
|
16
|
+
TimesArr.each do |interval|
|
17
|
+
rem = time % interval
|
18
|
+
occ = (time - rem) / interval
|
19
|
+
str.concat("#{occ}#{TimesRev[interval]} ") if occ > 0
|
20
|
+
time = rem
|
21
|
+
end
|
22
|
+
str end
|
23
|
+
|
24
|
+
private_class_method
|
25
|
+
# Calculate time interface (get an array of time entries, and calculate)
|
26
|
+
def self.calculate_time(time_arr)
|
27
|
+
time_arr.inject(0){|sum,el| sum += self.calculate_item(el)}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Calculate one time entry
|
31
|
+
def self.calculate_item(time_item)
|
32
|
+
magnitude = Times[time_item[-1]]
|
33
|
+
time_item.to_i * magnitude
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.count_occurences(time, step)
|
37
|
+
end
|
38
|
+
|
39
|
+
Times = {
|
40
|
+
'h' => 60 * 60,
|
41
|
+
's' => 1,
|
42
|
+
'm' => 60,
|
43
|
+
'd' => 8 * 60 * 60, # We assume logging a day = 8 hours
|
44
|
+
'w' => 8 * 60 * 60 * 7
|
45
|
+
}
|
46
|
+
|
47
|
+
# Reverse format for times
|
48
|
+
TimesRev = Hash[Times.to_a.collect{|arr| arr.reverse}]
|
49
|
+
|
50
|
+
# For a format to output a given int to time (1221 => 20m 21s)
|
51
|
+
TimesArr = Times.to_a.sort{|x1,x2| x2[1] <=> x1[1]}.collect{|e| e[1]}
|
52
|
+
end
|
53
|
+
end
|
@@ -3,13 +3,14 @@ module Wlog
|
|
3
3
|
# Store some ansi color codes in a module
|
4
4
|
# TODO this is a placeholder, and might not be correct.
|
5
5
|
module AnsiColors
|
6
|
-
|
7
|
-
|
8
|
-
Green =
|
9
|
-
|
10
|
-
|
6
|
+
Black = 30
|
7
|
+
Red = 31
|
8
|
+
Green = 32
|
9
|
+
Yellow = 33
|
10
|
+
Blue = 34
|
11
|
+
Magenta = 35
|
12
|
+
Cyan = 36
|
11
13
|
White = 37
|
12
|
-
Black = 38
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Wlog
|
2
|
+
# Use this if the system does not support colored strings.
|
3
|
+
# @author Simon Symeonidis
|
4
|
+
class UncoloredString
|
5
|
+
def self.red(str); str end
|
6
|
+
def self.yellow(str); str end
|
7
|
+
def self.magenta(str); str end
|
8
|
+
def self.green(str); str end
|
9
|
+
def self.blue(str); str end
|
10
|
+
def self.white(str); str end
|
11
|
+
def self.black(str); str end
|
12
|
+
def self.cyan(str); str end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'wlog/tech/ansi_colors'
|
2
|
+
|
3
|
+
module Wlog
|
4
|
+
# This should take care of multiplatform color stuff.
|
5
|
+
# @author Simon Symeonidis
|
6
|
+
class WlogString
|
7
|
+
include AnsiColors
|
8
|
+
|
9
|
+
def self.red(str); colorize(str,Red) end
|
10
|
+
def self.yellow(str); colorize(str,Yellow) end
|
11
|
+
def self.magenta(str); colorize(str,Magenta) end
|
12
|
+
def self.green(str); colorize(str,Green) end
|
13
|
+
def self.blue(str); colorize(str,Blue) end
|
14
|
+
def self.white(str); colorize(str,White) end
|
15
|
+
def self.black(str); colorize(str,Black) end
|
16
|
+
def self.cyan(str); colorize(str,Cyan) end
|
17
|
+
|
18
|
+
private
|
19
|
+
def self.colorize(str,col)
|
20
|
+
"\x1b[#{col};1m#{str}\x1b[0m"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'wlog/commands/innit_db'
|
2
|
+
require 'wlog/ui/setup_wizard'
|
3
|
+
require 'wlog/domain/helpers'
|
4
|
+
|
5
|
+
module Wlog
|
6
|
+
# This takes care of initialization. Place this class between the main entry
|
7
|
+
# point of the application and, the first transaction you require.
|
8
|
+
# @author Simon Symeonidis
|
9
|
+
class Bootstrap
|
10
|
+
def self.configure!
|
11
|
+
Helpers.make_dirs!
|
12
|
+
InnitDb.new.execute
|
13
|
+
# Initial setup if first time running
|
14
|
+
SetupWizard.new.run if Helpers.first_setup?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -1,10 +1,15 @@
|
|
1
|
+
require 'readline'
|
1
2
|
require 'turntables'
|
2
3
|
require 'wlog/domain/issue'
|
3
4
|
require 'wlog/domain/static_configurations'
|
4
5
|
require 'wlog/domain/sys_config'
|
5
6
|
require 'wlog/domain/attachment'
|
6
|
-
require 'wlog/
|
7
|
+
require 'wlog/domain/helpers'
|
7
8
|
require 'wlog/ui/commands/create_issue'
|
9
|
+
|
10
|
+
require 'wlog/commands/archive_issues'
|
11
|
+
require 'wlog/commands/archive_finished_issues'
|
12
|
+
require 'wlog/commands/delete_issue'
|
8
13
|
require 'wlog/ui/issue_ui'
|
9
14
|
|
10
15
|
module Wlog
|
@@ -16,26 +21,32 @@ class CliInterface
|
|
16
21
|
|
17
22
|
# This is the main entry point of the application. Therefore when we init,
|
18
23
|
# we want to trigger the table creation stuff.
|
19
|
-
def initialize
|
24
|
+
def initialize
|
25
|
+
@db = DbRegistry.new(nil)
|
26
|
+
@strmaker = SysConfig.string_decorator
|
27
|
+
end
|
20
28
|
|
21
29
|
# Run the interface
|
22
30
|
def run
|
23
31
|
cmd = "default"
|
32
|
+
label = @strmaker.white('wlog')
|
24
33
|
until cmd == "end" do
|
25
|
-
|
26
|
-
cmd = $stdin.gets || "end"
|
34
|
+
cmd = Readline.readline("[#{label}] ") || "end"
|
27
35
|
cmd.chomp!
|
28
36
|
|
29
37
|
case cmd
|
38
|
+
when /archive/ then archive cmd
|
30
39
|
when /showattach/ then show_attach
|
31
40
|
when /outattach/ then output_attach
|
41
|
+
when /generateinvoice/ then generate_invoice
|
32
42
|
when /attach/ then attach
|
33
43
|
when /focus/ then focus
|
34
44
|
when /new/ then new_issue
|
35
45
|
when /show/ then show_issues
|
36
46
|
when /outcsv/ then outcsv
|
37
|
-
when /delete/ then
|
47
|
+
when /delete/ then delete_issue
|
38
48
|
when /help/ then print_help
|
49
|
+
when /search/ then search
|
39
50
|
end
|
40
51
|
end
|
41
52
|
end
|
@@ -51,16 +62,22 @@ class CliInterface
|
|
51
62
|
private
|
52
63
|
|
53
64
|
# Create a new issue
|
54
|
-
def new_issue; CreateIssue.new.execute end
|
65
|
+
def new_issue; CreateIssue.new(@db).execute end
|
66
|
+
|
67
|
+
# Procedure to delete an issue
|
68
|
+
def delete_issue
|
69
|
+
issue_id = Readline.readline('Which issue id to delete? : ').to_i
|
70
|
+
dcmd = DeleteIssue.new(@db, issue_id)
|
71
|
+
dcmd.execute
|
72
|
+
puts "No such issue" unless dcmd.deleted?
|
73
|
+
end
|
55
74
|
|
56
75
|
# Wriet out the data contained in the database of the attachment
|
57
76
|
def output_attach
|
58
|
-
|
59
|
-
|
60
|
-
print "Output where (abs dir) : "
|
61
|
-
loc = $stdin.gets
|
77
|
+
att_id = Readline.readline('Which attachment to output? : ').to_i
|
78
|
+
loc = Readline.readline('Output where (abs dir) ? : ')
|
62
79
|
loc.chomp!
|
63
|
-
att = Attachment.find(Issue.name, att_id)
|
80
|
+
att = Attachment.find(@db, Issue.name, att_id)
|
64
81
|
|
65
82
|
fh = File.open("#{loc}/#{att.filename}", 'w')
|
66
83
|
fh.write(att.data)
|
@@ -68,30 +85,46 @@ private
|
|
68
85
|
end
|
69
86
|
|
70
87
|
def show_attach
|
71
|
-
|
72
|
-
|
73
|
-
atts = Attachment.find_all_by_discriminator(Issue.name, issue_id)
|
88
|
+
issue_id = Readline.readline('Which issue id? : ').to_i
|
89
|
+
atts = Attachment.find_all_by_discriminator(@db, Issue.name, issue_id)
|
74
90
|
atts.each do |att|
|
75
91
|
printf "[%d] - %s (alias: %s)\n", att.id, att.filename, att.given_name
|
76
92
|
end
|
77
93
|
end
|
78
94
|
|
95
|
+
# Archive means set status to 3 (arhive status) to the listed issues
|
96
|
+
def archive(cmd)
|
97
|
+
args = cmd.split[1..-1]
|
98
|
+
|
99
|
+
if args.length > 0
|
100
|
+
if args[0] == 'finished'
|
101
|
+
puts "Archiving finished issues."
|
102
|
+
ArchiveFinishedIssues.new(@db).execute
|
103
|
+
else # gave ids
|
104
|
+
ids = args.map{|sids| sids.to_i}
|
105
|
+
issues = ids.map{|id| Issue.find(@db, id)} - [nil]
|
106
|
+
ArchiveIssues.new(issues).execute
|
107
|
+
end
|
108
|
+
else
|
109
|
+
puts "usage: "
|
110
|
+
puts " archive finished"
|
111
|
+
puts " archive <id>+"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
79
115
|
def attach
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
print "Alias name for file (optional) :"
|
86
|
-
name_alias = $stdin.gets
|
87
|
-
name_alias.chomp!
|
116
|
+
issue_id = Readline.readline('Attach to issue id: ').to_i
|
117
|
+
loc = Readline.readline('Absolute file location: ')
|
118
|
+
loc.strip!
|
119
|
+
name_alias = Readline.readline('Alias name for file (optional): ')
|
120
|
+
name_alias.strip!
|
88
121
|
|
89
122
|
unless loc.nil?
|
90
123
|
fh = File.open(loc, "r")
|
91
124
|
data = fh.read
|
92
125
|
fh.close
|
93
126
|
|
94
|
-
att = Attachment.new(Issue.name, issue_id)
|
127
|
+
att = Attachment.new(@db, Issue.name, issue_id)
|
95
128
|
att.data = data
|
96
129
|
att.filename = loc.split('/').last
|
97
130
|
att.given_name = name_alias
|
@@ -103,11 +136,13 @@ private
|
|
103
136
|
end
|
104
137
|
|
105
138
|
def focus
|
106
|
-
|
107
|
-
|
108
|
-
issue
|
109
|
-
|
110
|
-
|
139
|
+
issue_id = Readline.readline('Focus on issue : ').to_i
|
140
|
+
issue = Issue.find(@db, issue_id)
|
141
|
+
if issue
|
142
|
+
IssueUi.new(@db, issue).run
|
143
|
+
else
|
144
|
+
puts "No such issue"
|
145
|
+
end
|
111
146
|
end
|
112
147
|
|
113
148
|
def outcsv
|
@@ -117,6 +152,7 @@ private
|
|
117
152
|
fh.close
|
118
153
|
end
|
119
154
|
|
155
|
+
# FIXME (update the command stuff)
|
120
156
|
# Print the help of the cli app
|
121
157
|
def print_help
|
122
158
|
["new", "Create a new log entry",
|
@@ -129,24 +165,48 @@ private
|
|
129
165
|
end
|
130
166
|
end
|
131
167
|
|
132
|
-
# TODO might need refactoring
|
133
168
|
def show_issues
|
134
|
-
entries_arr = Issue.find_all
|
169
|
+
entries_arr = Issue.find_all(@db)
|
170
|
+
print_list(entries_arr)
|
171
|
+
end
|
172
|
+
|
173
|
+
# TODO might need refactoring
|
174
|
+
def print_list(entries_arr)
|
135
175
|
issue_collections = entries_arr.reverse.group_by{|iss| iss.status_s}
|
136
176
|
issue_collections.each_key do |stat|
|
137
|
-
print "
|
138
|
-
puts "
|
177
|
+
print @strmaker.green("#{stat}")
|
178
|
+
puts @strmaker.magenta(" #{issue_collections[stat].count}")
|
139
179
|
issue_collections[stat].each do |iss|
|
140
|
-
|
180
|
+
print @strmaker.red(" [#{iss.id}] ")
|
181
|
+
puts "#{iss.description}"
|
141
182
|
end
|
142
183
|
end
|
143
184
|
end
|
144
185
|
|
145
186
|
def make_csv
|
146
|
-
cmd = MakeCsv.new
|
187
|
+
cmd = MakeCsv.new(@db)
|
147
188
|
cmd.execute
|
148
189
|
cmd.ret
|
149
190
|
end
|
191
|
+
|
192
|
+
def generate_invoice
|
193
|
+
require 'time'
|
194
|
+
puts "Eg: valid input is Oct 2013 15"
|
195
|
+
from = Readline.readline("From: ")
|
196
|
+
to = Readline.readline("To : ")
|
197
|
+
|
198
|
+
from_time = Time.parse(from).to_i
|
199
|
+
to_time = Time.parse(to).to_i
|
200
|
+
issues = Issue.find_in_time_range(@db, from_time, to_time)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Search for an issue
|
204
|
+
def search
|
205
|
+
term = Readline.readline("search issues for term : ")
|
206
|
+
issues = Issue.find_all(@db).select{|el| el.description.match(/#{term}/)}
|
207
|
+
print_list(issues)
|
208
|
+
end
|
209
|
+
|
150
210
|
end
|
151
211
|
end # module Wlog
|
152
212
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'readline'
|
1
2
|
require 'wlog/ui/commands/ui_command'
|
2
3
|
require 'wlog/domain/issue'
|
3
4
|
|
@@ -5,14 +6,17 @@ module Wlog
|
|
5
6
|
# Creational logic for issues
|
6
7
|
# @author Simon Symeonidis
|
7
8
|
class CreateIssue < UiCommand
|
9
|
+
def initialize(db)
|
10
|
+
@db = db
|
11
|
+
end
|
12
|
+
|
13
|
+
# Execute create issue transaction
|
8
14
|
def execute
|
9
|
-
@ret = Issue.new
|
10
|
-
|
11
|
-
desc = $stdin.gets || "None."
|
15
|
+
@ret = Issue.new(@db)
|
16
|
+
desc = Readline.readline("Small issue description :") || "None."
|
12
17
|
@ret.description = desc.chomp
|
13
18
|
@ret.insert
|
14
19
|
end
|
15
|
-
|
16
20
|
attr_accessor :ret
|
17
21
|
end
|
18
22
|
end
|
data/lib/wlog/ui/issue_ui.rb
CHANGED
@@ -1,38 +1,43 @@
|
|
1
|
+
require 'readline'
|
2
|
+
|
1
3
|
require 'wlog/commands/replace_pattern'
|
2
4
|
require 'wlog/commands/new_entry'
|
3
5
|
require 'wlog/commands/make_csv'
|
4
6
|
require 'wlog/commands/innit_db'
|
5
7
|
require 'wlog/commands/concat_description'
|
8
|
+
require 'wlog/domain/sys_config'
|
9
|
+
require 'wlog/domain/timelog_helper'
|
6
10
|
|
7
11
|
module Wlog
|
8
12
|
# The interface when focusing on an issue
|
9
13
|
# @author Simon
|
10
14
|
class IssueUi
|
11
|
-
def initialize(issue)
|
15
|
+
def initialize(db, issue)
|
12
16
|
@issue = issue
|
17
|
+
@db = db
|
18
|
+
@strmaker = SysConfig.string_decorator
|
13
19
|
end
|
14
20
|
|
15
21
|
# Start up the interface
|
16
22
|
def run
|
17
23
|
cmd = "default"
|
18
24
|
until cmd == "end" do
|
19
|
-
|
20
|
-
cmd = $stdin.gets || ""
|
25
|
+
cmd = Readline.readline("[issue ##{@issue.id}] ") || ""
|
21
26
|
cmd.chomp!
|
22
27
|
|
23
28
|
case cmd
|
24
|
-
when /
|
25
|
-
when /
|
26
|
-
when /
|
27
|
-
when /
|
28
|
-
when /
|
29
|
-
when /
|
30
|
-
when /
|
31
|
-
when /
|
32
|
-
when /
|
33
|
-
when
|
34
|
-
when
|
35
|
-
when
|
29
|
+
when /^new/ then new_entry
|
30
|
+
when /^show/ then show_entries
|
31
|
+
when /^desc/ then describe_issue
|
32
|
+
when /^delete/ then delete_entry
|
33
|
+
when /^search/ then search_term
|
34
|
+
when /^concat/ then concat_description
|
35
|
+
when /^replace/ then replace_pattern
|
36
|
+
when /^search/ then search_term
|
37
|
+
when /^lt/ then time(cmd.split.drop 1) # lt for log time
|
38
|
+
when /^forget/ then cmd = "end"
|
39
|
+
when /^finish/ then finish.nil? ? nil : cmd = "end"
|
40
|
+
when /^help/ then print_help
|
36
41
|
else puts "Type 'help' for help"
|
37
42
|
end
|
38
43
|
end
|
@@ -43,6 +48,13 @@ class IssueUi
|
|
43
48
|
|
44
49
|
private
|
45
50
|
|
51
|
+
# Time logging command
|
52
|
+
def time(rest)
|
53
|
+
time = TimelogHelper.parse(rest.join)
|
54
|
+
@issue.log_time(time)
|
55
|
+
puts @strmaker.green('logged time!')
|
56
|
+
end
|
57
|
+
|
46
58
|
# Print the description of the issue
|
47
59
|
def describe_issue; puts @issue end
|
48
60
|
|
@@ -61,8 +73,8 @@ private
|
|
61
73
|
|
62
74
|
# Exit the issue, mark as finished
|
63
75
|
def finish
|
64
|
-
|
65
|
-
if ret =
|
76
|
+
question = 'Are you done with this task? [yes/no] :'
|
77
|
+
if ret = !! Readline.readline(question).match(/^yes/i)
|
66
78
|
@issue.mark_finished!
|
67
79
|
@issue.update
|
68
80
|
end
|
@@ -70,52 +82,46 @@ private
|
|
70
82
|
|
71
83
|
# new entry command
|
72
84
|
def new_entry
|
73
|
-
|
74
|
-
description
|
85
|
+
description = Readline.readline("Enter new issue:#{$/} ")
|
86
|
+
description.chomp!
|
75
87
|
@issue.mark_working!
|
76
88
|
@issue.update
|
77
|
-
NewEntry.new(description, @issue.id).execute
|
89
|
+
NewEntry.new(@db, description, @issue.id).execute
|
78
90
|
end
|
79
91
|
|
80
92
|
def delete_entry
|
81
|
-
|
82
|
-
LogEntry.
|
93
|
+
id = Readline.readline('Remove task log with id : ').to_i
|
94
|
+
LogEntry.delete_by_id(@db, id)
|
83
95
|
end
|
84
96
|
|
85
97
|
# Concatenate an aggregate description to a previous item
|
86
98
|
def concat_description
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
str = $stdin.gets.chomp!
|
91
|
-
ConcatDescription.new(id, str).execute
|
99
|
+
id = Readline.readline("ID of task to concatenate to: ").to_i
|
100
|
+
str = Readline.readline("Information to concatenate: ").chomp
|
101
|
+
ConcatDescription.new(@db, id, str).execute
|
92
102
|
end
|
93
103
|
|
94
104
|
# Replace a pattern from a description of a log entry
|
95
105
|
def replace_pattern
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
old_pattern
|
100
|
-
print "with : "
|
101
|
-
new_pattern = $stdin.gets.chomp!
|
102
|
-
ReplacePattern.new(id, old_pattern, new_pattern).execute
|
106
|
+
id = Readline.readline("ID of task to perform replace: ").to_i
|
107
|
+
old_pattern = Readline.readline('replace : ').chomp
|
108
|
+
new_pattern = Readline.readline('with : ').chomp
|
109
|
+
ReplacePattern.new(@db, id, old_pattern, new_pattern).execute
|
103
110
|
end
|
104
111
|
|
105
112
|
def search_term
|
106
|
-
|
107
|
-
term
|
108
|
-
print_entries(LogEntry.search_descriptions(term))
|
113
|
+
term = Readline.readline('search : ').chomp!
|
114
|
+
print_entries(LogEntry.search_descriptions(@db, term))
|
109
115
|
end
|
110
116
|
|
111
117
|
# TODO might need refactoring
|
112
118
|
def show_entries
|
113
|
-
entries_arr = LogEntry.find_all_by_issue_id @issue.id
|
119
|
+
entries_arr = LogEntry.find_all_by_issue_id(@db, @issue.id)
|
114
120
|
date_collections = entries_arr.group_by{|le| le.date.strftime("%Y-%m-%d")}
|
115
121
|
date_collections.each_key do |date_c|
|
116
|
-
print "
|
117
|
-
print
|
118
|
-
puts "[
|
122
|
+
print @strmaker.green("#{date_c} - ")
|
123
|
+
print @strmaker.yellow(date_collections[date_c].first.date.strftime("%A"))
|
124
|
+
puts " [#{@strmaker.magenta(date_collections[date_c].count.to_s)}]"
|
119
125
|
date_collections[date_c].each do |le|
|
120
126
|
puts " #{le}"
|
121
127
|
end
|