wlog 1.1.1 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -48
- data/Rakefile +1 -0
- data/lib/wlog/commands/archive_finished_issues.rb +2 -2
- data/lib/wlog/commands/archive_issues.rb +1 -1
- data/lib/wlog/commands/bootstrap_templates.rb +37 -0
- data/lib/wlog/commands/concat_description.rb +7 -11
- data/lib/wlog/commands/delete_issue.rb +6 -5
- data/lib/wlog/commands/innit_db.rb +62 -6
- data/lib/wlog/commands/make_csv.rb +2 -6
- data/lib/wlog/commands/new_entry.rb +10 -7
- data/lib/wlog/commands/replace_pattern.rb +7 -5
- data/lib/wlog/domain/attachment.rb +50 -75
- data/lib/wlog/domain/invoice.rb +8 -2
- data/lib/wlog/domain/issue.rb +32 -132
- data/lib/wlog/domain/key_value.rb +10 -35
- data/lib/wlog/domain/log_entry.rb +18 -95
- data/lib/wlog/domain/static_configurations.rb +6 -0
- data/lib/wlog/domain/sys_config.rb +2 -5
- data/lib/wlog/migrations/make_standard_tables.rb +59 -0
- data/lib/wlog/ui/cli_interface.rb +55 -44
- data/lib/wlog/ui/commands/create_issue.rb +4 -8
- data/lib/wlog/ui/edit_handler.rb +74 -0
- data/lib/wlog/ui/invoice_ui.rb +133 -0
- data/lib/wlog/ui/issue_ui.rb +21 -77
- data/lib/wlog/ui/template_ui.rb +66 -0
- data/lib/wlog/version.rb +1 -1
- data/spec/domain/attachment_spec.rb +58 -59
- data/spec/domain/commands/concat_desc_spec.rb +10 -13
- data/spec/domain/commands/new_entry_spec.rb +10 -13
- data/spec/domain/commands/replace_pattern_spec.rb +11 -12
- data/spec/domain/issue_spec.rb +35 -38
- data/spec/domain/key_value_spec.rb +5 -8
- data/spec/domain/log_entry_spec.rb +20 -31
- data/spec/domain/sys_config_spec.rb +4 -7
- data/spec/make_db.rb +30 -4
- data/spec/tech/wlog_string_spec.rb +14 -14
- data/wlog.gemspec +2 -1
- metadata +26 -13
- data/lib/wlog/db_registry.rb +0 -38
- data/lib/wlog/domain/sql_modules/attachment_sql.rb +0 -21
- data/lib/wlog/domain/sql_modules/issue_sql.rb +0 -37
- data/lib/wlog/domain/sql_modules/key_value_sql.rb +0 -20
- data/lib/wlog/domain/sql_modules/log_entry_sql.rb +0 -35
- data/lib/wlog/ui/commands/attach_to_issue.rb +0 -0
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'readline'
|
2
|
-
require 'turntables'
|
3
2
|
require 'wlog/domain/issue'
|
4
3
|
require 'wlog/domain/static_configurations'
|
5
4
|
require 'wlog/domain/sys_config'
|
@@ -13,6 +12,8 @@ require 'wlog/commands/archive_issues'
|
|
13
12
|
require 'wlog/commands/archive_finished_issues'
|
14
13
|
require 'wlog/commands/delete_issue'
|
15
14
|
require 'wlog/ui/issue_ui'
|
15
|
+
require 'wlog/ui/template_ui'
|
16
|
+
require 'wlog/ui/invoice_ui'
|
16
17
|
|
17
18
|
module Wlog
|
18
19
|
# @author Simon Symeonidis
|
@@ -24,7 +25,6 @@ class CliInterface
|
|
24
25
|
# This is the main entry point of the application. Therefore when we init,
|
25
26
|
# we want to trigger the table creation stuff.
|
26
27
|
def initialize
|
27
|
-
@db = DbRegistry.new(nil)
|
28
28
|
@strmaker = SysConfig.string_decorator
|
29
29
|
end
|
30
30
|
|
@@ -43,13 +43,15 @@ class CliInterface
|
|
43
43
|
when /^generateinvoice/ then generate_invoice
|
44
44
|
when /^attach/ then attach
|
45
45
|
when /^focus/ then focus(cmd)
|
46
|
-
when
|
46
|
+
when /new/ then new_issue
|
47
47
|
when /^(ls|show)/ then show_issues
|
48
48
|
when /^outcsv/ then outcsv
|
49
49
|
when /^delete/ then delete_issue(cmd)
|
50
50
|
when /^help/ then print_help
|
51
51
|
when /^search/ then search
|
52
52
|
when /^config/ then config
|
53
|
+
when /^templates/ then TemplateUi.new.run
|
54
|
+
when /^invoices/ then InvoiceUi.new.run
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
@@ -65,34 +67,38 @@ class CliInterface
|
|
65
67
|
private
|
66
68
|
|
67
69
|
# Create a new issue
|
68
|
-
def new_issue; CreateIssue.new
|
70
|
+
def new_issue; CreateIssue.new.execute end
|
69
71
|
|
70
72
|
# Procedure to delete an issue
|
71
73
|
def delete_issue(cmd)
|
72
74
|
issue_id = cmd.split[1]
|
73
75
|
|
74
76
|
if !issue_id
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
dcmd = DeleteIssue.new(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
77
|
+
puts 'usage:'
|
78
|
+
puts ' delete <id>'
|
79
|
+
else
|
80
|
+
issue_id = issue_id.to_i
|
81
|
+
end
|
82
|
+
|
83
|
+
dcmd = DeleteIssue.new(issue_id)
|
84
|
+
if dcmd
|
85
|
+
choice = Readline.readline("Delete issue #{issue_id}? [y/n]").strip
|
86
|
+
if choice == "y"
|
87
|
+
dcmd.execute
|
88
|
+
else
|
89
|
+
puts "Did nothing"
|
90
|
+
return
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
91
94
|
puts "No such issue" unless dcmd.deleted?
|
92
95
|
end
|
93
96
|
|
94
97
|
# Wriet out the data contained in the database of the attachment
|
95
98
|
def output_attach
|
99
|
+
puts "Migration of implementation pending"
|
100
|
+
return
|
101
|
+
|
96
102
|
att_id = Readline.readline('Which attachment to output? : ').to_i
|
97
103
|
loc = Readline.readline('Output where (abs dir) ? : ')
|
98
104
|
loc.chomp!
|
@@ -104,6 +110,8 @@ private
|
|
104
110
|
end
|
105
111
|
|
106
112
|
def show_attach
|
113
|
+
puts "Migration of implementation pending"
|
114
|
+
return
|
107
115
|
issue_id = Readline.readline('Which issue id? : ').to_i
|
108
116
|
atts = Attachment.find_all_by_discriminator(@db, Issue.name, issue_id)
|
109
117
|
atts.each do |att|
|
@@ -118,7 +126,7 @@ private
|
|
118
126
|
if args.length > 0
|
119
127
|
if args[0] == 'finished'
|
120
128
|
puts "Archiving finished issues."
|
121
|
-
ArchiveFinishedIssues.new
|
129
|
+
ArchiveFinishedIssues.new.execute
|
122
130
|
else # gave ids
|
123
131
|
ids = args.map{|sids| sids.to_i}
|
124
132
|
issues = ids.map{|id| Issue.find(@db, id)} - [nil]
|
@@ -132,6 +140,9 @@ private
|
|
132
140
|
end
|
133
141
|
|
134
142
|
def attach
|
143
|
+
puts "Migration of implementation pending"
|
144
|
+
return
|
145
|
+
|
135
146
|
issue_id = Readline.readline('Attach to issue id: ').to_i
|
136
147
|
loc = Readline.readline('Absolute file location: ')
|
137
148
|
loc.strip!
|
@@ -157,17 +168,17 @@ private
|
|
157
168
|
# Focus on an issue to log work etc
|
158
169
|
def focus(cmd)
|
159
170
|
issue_id = cmd.split[1]
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
issue = Issue.find(
|
171
|
+
if !issue_id
|
172
|
+
puts 'usage: '
|
173
|
+
puts ' focus <id>'
|
174
|
+
return
|
175
|
+
else
|
176
|
+
issue_id = issue_id.to_i
|
177
|
+
end
|
178
|
+
|
179
|
+
issue = Issue.find(issue_id)
|
169
180
|
if issue
|
170
|
-
IssueUi.new(
|
181
|
+
IssueUi.new(issue).run
|
171
182
|
else
|
172
183
|
puts "No such issue"
|
173
184
|
end
|
@@ -188,23 +199,23 @@ private
|
|
188
199
|
'help', 'print this dialog',
|
189
200
|
'end', 'Exit the progam',
|
190
201
|
'delete', 'Remove the issue with a given id',
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
202
|
+
'archive', 'Archive a file into a specific issue',
|
203
|
+
'showattach', 'Show what files have been attached to an issue',
|
204
|
+
'outattach', 'Extract a file from the database',
|
205
|
+
'generateinvoice', 'todo',
|
206
|
+
'focus', 'Focus on a particular ',
|
207
|
+
'show', 'List all the issues',
|
208
|
+
'help', 'Show this information',
|
209
|
+
'search', 'Search for a specific text',
|
210
|
+
'config', 'Set differeing configuration parameters'
|
211
|
+
].each_with_index do |el,ix|
|
201
212
|
print ' ' if 1 == ix % 2
|
202
213
|
puts el
|
203
214
|
end
|
204
215
|
end
|
205
216
|
|
206
217
|
def show_issues
|
207
|
-
entries_arr = Issue.
|
218
|
+
entries_arr = Issue.find_not_archived
|
208
219
|
print_list(entries_arr)
|
209
220
|
end
|
210
221
|
|
@@ -229,7 +240,7 @@ private
|
|
229
240
|
end
|
230
241
|
|
231
242
|
def make_csv
|
232
|
-
cmd = MakeCsv.new
|
243
|
+
cmd = MakeCsv.new
|
233
244
|
cmd.execute
|
234
245
|
cmd.ret
|
235
246
|
end
|
@@ -248,7 +259,7 @@ private
|
|
248
259
|
# Search for an issue
|
249
260
|
def search
|
250
261
|
term = Readline.readline("search issues for term : ")
|
251
|
-
issues = Issue.
|
262
|
+
issues = Issue.where(["description like ?", "%#{term}%"])
|
252
263
|
print_list(issues)
|
253
264
|
end
|
254
265
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'active_record'
|
1
2
|
require 'readline'
|
2
3
|
require 'wlog/ui/commands/ui_command'
|
3
4
|
require 'wlog/domain/issue'
|
@@ -6,18 +7,13 @@ module Wlog
|
|
6
7
|
# Creational logic for issues
|
7
8
|
# @author Simon Symeonidis
|
8
9
|
class CreateIssue < UiCommand
|
9
|
-
def initialize(db)
|
10
|
-
@db = db
|
11
|
-
end
|
12
|
-
|
13
10
|
# Execute create issue transaction
|
14
11
|
def execute
|
15
|
-
@ret = Issue.new(@db)
|
16
12
|
desc = Readline.readline("Small issue description :") || "None."
|
17
13
|
ldesc = Readline.readline("Long issue description :") || "None."
|
18
|
-
@ret.description
|
19
|
-
|
20
|
-
|
14
|
+
@ret = Issue.create(:description =>desc.chomp, :long_description => ldesc,
|
15
|
+
:status => 0, :created_at => Time.now, :updated_at => Time.now,
|
16
|
+
:due_date => Time.now, :timelog => 0)
|
21
17
|
end
|
22
18
|
attr_accessor :ret
|
23
19
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
module Wlog
|
3
|
+
# @author Simon Symeonidis
|
4
|
+
class EditHandler
|
5
|
+
|
6
|
+
def initialize(issue); @issue = issue end
|
7
|
+
|
8
|
+
# Command comes in as edit <...>. This definition will check what comes
|
9
|
+
# next and invoke the proper method to execute.
|
10
|
+
def edit_what(terms_a)
|
11
|
+
case terms_a[0]
|
12
|
+
when /^title/
|
13
|
+
title = (terms_a.drop 1).join ' '
|
14
|
+
@issue.description = title
|
15
|
+
@issue.update
|
16
|
+
|
17
|
+
when /^desc/
|
18
|
+
long = (terms_a.drop 1).join ' '
|
19
|
+
@issue.long_description = long
|
20
|
+
@issue.update
|
21
|
+
|
22
|
+
when /^due/
|
23
|
+
date_time = terms_a.drop 1
|
24
|
+
edit_time(date_time.join(' '))
|
25
|
+
|
26
|
+
when /^reported/
|
27
|
+
date_time = terms_a.drop 1
|
28
|
+
edit_reported_time(date_time.join(' '))
|
29
|
+
|
30
|
+
else
|
31
|
+
$stdout.puts "Usage: "
|
32
|
+
$stdout.puts " edit title - to edit the title"
|
33
|
+
$stdout.puts " edit desc - to edit the long description"
|
34
|
+
$stdout.puts " edit due - to edit the due date"
|
35
|
+
$stdout.puts " edit time - to edit the time"
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param time is the date-time in string format (eg Oct 28)
|
41
|
+
def edit_time(time)
|
42
|
+
date_time = time_handle(time)
|
43
|
+
@issue.due_date = date_time.to_time
|
44
|
+
@issue.update
|
45
|
+
puts @strmaker.green('Updated due date')
|
46
|
+
rescue ArgumentError
|
47
|
+
$stderr.puts @strmaker.red \
|
48
|
+
"Invalid date/time format. Try format like 'Oct 28'"
|
49
|
+
end
|
50
|
+
|
51
|
+
def edit_reported_time(time_str)
|
52
|
+
date_time = time_handle(time_str)
|
53
|
+
@issue.reported_date = date_time.to_time
|
54
|
+
@issue.update
|
55
|
+
puts @strmaker.green('Updated reported date')
|
56
|
+
rescue ArgumentError
|
57
|
+
$stderr.puts @strmaker.red \
|
58
|
+
"Invalid date/time format. Try format like 'Oct 28'"
|
59
|
+
end
|
60
|
+
|
61
|
+
# TODO fix me
|
62
|
+
# @param time_str The time that we want to kind of sanitize
|
63
|
+
# @return a Time object which is set to 9am on that day if no time
|
64
|
+
# is provided
|
65
|
+
def time_handle(time_str)
|
66
|
+
date_time = DateTime.parse(time)
|
67
|
+
date_time = DateTime.parse(time + ' 9:00') if date_time.hour == 0
|
68
|
+
end
|
69
|
+
|
70
|
+
# Pass the issue from the previous ui to this one. This ui modifies
|
71
|
+
attr :issue
|
72
|
+
|
73
|
+
end
|
74
|
+
end # wlog
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'readline'
|
2
|
+
require 'wlog/domain/invoice'
|
3
|
+
require 'wlog/domain/sys_config'
|
4
|
+
require 'wlog/domain/static_configurations'
|
5
|
+
require 'erb'
|
6
|
+
|
7
|
+
module Wlog
|
8
|
+
# An interface for the invoices
|
9
|
+
# @author Simon Symeonidis
|
10
|
+
class InvoiceUi
|
11
|
+
include StaticConfigurations
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@strmaker = SysConfig.string_decorator
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
cmd = "default"
|
19
|
+
|
20
|
+
while cmd != 'end'
|
21
|
+
cmd = Readline.readline("[#{@strmaker.red('invoice')}] ") || ""
|
22
|
+
case cmd
|
23
|
+
when /^new/ then make_invoice
|
24
|
+
when /^(ls|show)/ then ls
|
25
|
+
when /^delete/ then delete(cmd.split.drop 1)
|
26
|
+
when /^generate/ then generate(cmd.split.drop 1)
|
27
|
+
when /^end/ then next
|
28
|
+
else
|
29
|
+
puts "type 'help' for a list of options"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# TODO maybe separate this in the future for better testing.
|
37
|
+
def generate(rest)
|
38
|
+
num = rest.first || 1
|
39
|
+
invoice = Invoice.find(num.to_i)
|
40
|
+
|
41
|
+
# NOTE: these need to be instance vars, so we expose them to ERB later on
|
42
|
+
@les = invoice.log_entries_within_dates
|
43
|
+
@issues = [Issue.find(*(@les.collect(&:issue_id).uniq))].compact.flatten
|
44
|
+
|
45
|
+
# Get the template
|
46
|
+
num = SysConfig.get_config('template') || 1
|
47
|
+
tpath = Dir[TemplateDir + '*'][num.to_i - 1]
|
48
|
+
template_s = File.read(tpath)
|
49
|
+
|
50
|
+
renderer = ERB.new(template_s)
|
51
|
+
output = renderer.result(binding)
|
52
|
+
|
53
|
+
FileUtils.mkdir_p TemplateOutputDir
|
54
|
+
template_ext = tpath.split(File::SEPARATOR).last.split('.').last
|
55
|
+
filename = TemplateOutputDir + "#{invoice.id}-invoice.#{template_ext}"
|
56
|
+
|
57
|
+
File.write(filename, output)
|
58
|
+
|
59
|
+
rescue ActiveRecord::RecordNotFound
|
60
|
+
puts 'No such invoice'
|
61
|
+
rescue => e
|
62
|
+
puts e.message
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete(rest)
|
66
|
+
id = rest[0]
|
67
|
+
cmd = Readline.readline("Are you sure you want to delete invoice ##{id}? [y/n]: ")
|
68
|
+
return if cmd != 'y'
|
69
|
+
Invoice.delete(id)
|
70
|
+
end
|
71
|
+
|
72
|
+
def ls
|
73
|
+
Invoice.all.each do |invoice|
|
74
|
+
print " [#{invoice.id}] "
|
75
|
+
print @strmaker.yellow(invoice.from.strftime("%d-%m-%Y"))
|
76
|
+
print @strmaker.blue(" -> ")
|
77
|
+
print @strmaker.yellow(invoice.to.strftime("%d-%m-%Y"))
|
78
|
+
puts " #{invoice.description.split.first}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def print_help
|
83
|
+
['new', 'make a new invoice',
|
84
|
+
'ls,show', 'list the current invoice templates',
|
85
|
+
'delete', 'delete an invoice (eg: delete 2)',
|
86
|
+
'generate', 'generate an invoice using set template (eg: generate 2)'
|
87
|
+
].each_with_index do |cmd,ix|
|
88
|
+
print ' ' if ix % 2 == 1
|
89
|
+
puts cmd
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# TODO this should be extracted for testing
|
94
|
+
def make_invoice
|
95
|
+
from_s = Readline.readline("#{@strmaker.blue('From')} (dd-mm-yyyy) ")
|
96
|
+
to_s = Readline.readline("#{@strmaker.blue('To')} (dd-mm-yyyy) ")
|
97
|
+
|
98
|
+
from_d = DateTime.parse(from_s)
|
99
|
+
to_d = DateTime.parse(to_s + " 23:59")
|
100
|
+
description = longtext()
|
101
|
+
|
102
|
+
Invoice.create(:from => from_d, :to => to_d, :description => description)
|
103
|
+
end
|
104
|
+
|
105
|
+
# TODO: this would have to be factored out at some point. Also I think the
|
106
|
+
# implementation is crappy. I have to recheck at some point.
|
107
|
+
def longtext
|
108
|
+
times = 3
|
109
|
+
str = ""
|
110
|
+
count = 0
|
111
|
+
|
112
|
+
while times != 0 do
|
113
|
+
cur = Readline.readline()
|
114
|
+
str.concat(cur)
|
115
|
+
str.concat($/)
|
116
|
+
if ["", nil].include? cur
|
117
|
+
str.concat($/)
|
118
|
+
count += 1
|
119
|
+
if count == 2
|
120
|
+
times -= 1
|
121
|
+
count = 0
|
122
|
+
end
|
123
|
+
else
|
124
|
+
# reset blank line count. The user will have to hammer enter a few times
|
125
|
+
# to escape from this menu
|
126
|
+
count = 0
|
127
|
+
end
|
128
|
+
end
|
129
|
+
str end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
data/lib/wlog/ui/issue_ui.rb
CHANGED
@@ -8,14 +8,14 @@ require 'wlog/commands/innit_db'
|
|
8
8
|
require 'wlog/commands/concat_description'
|
9
9
|
require 'wlog/domain/sys_config'
|
10
10
|
require 'wlog/domain/timelog_helper'
|
11
|
+
require 'wlog/ui/edit_handler'
|
11
12
|
|
12
13
|
module Wlog
|
13
14
|
# The interface when focusing on an issue
|
14
15
|
# @author Simon
|
15
16
|
class IssueUi
|
16
|
-
def initialize(
|
17
|
+
def initialize(issue)
|
17
18
|
@issue = issue
|
18
|
-
@db = db
|
19
19
|
@strmaker = SysConfig.string_decorator
|
20
20
|
end
|
21
21
|
|
@@ -31,13 +31,13 @@ class IssueUi
|
|
31
31
|
when /^(ls|show)/ then show_entries
|
32
32
|
when /^desc/ then describe_issue
|
33
33
|
when /^delete/ then delete_entry
|
34
|
-
when /^edit/ then edit_what(cmd.split.drop 1)
|
34
|
+
when /^edit/ then EditHandler.new(@issue).edit_what(cmd.split.drop 1)
|
35
35
|
when /^concat/ then concat_description
|
36
36
|
when /^replace/ then replace_pattern
|
37
|
-
when /^search/ then search_term(cmd.split.drop 1)
|
37
|
+
when /^search/ then search_term((cmd.split.drop 1).join ' ')
|
38
38
|
when /^lt/ then time(cmd.split.drop 1) # lt for log time
|
39
39
|
when /^forget/ then cmd = "end"
|
40
|
-
when /^finish/ then finish
|
40
|
+
when /^finish/ then finish ? cmd = "end" : nil
|
41
41
|
when /^help/ then print_help
|
42
42
|
when /^end/ then next
|
43
43
|
else puts "Type 'help' for help"
|
@@ -78,7 +78,7 @@ private
|
|
78
78
|
question = 'Are you done with this task? [yes/no] :'
|
79
79
|
if ret = !! Readline.readline(question).match(/^yes/i)
|
80
80
|
@issue.mark_finished!
|
81
|
-
@issue.
|
81
|
+
@issue.save
|
82
82
|
end
|
83
83
|
ret end
|
84
84
|
|
@@ -87,20 +87,21 @@ private
|
|
87
87
|
description = Readline.readline("Enter new issue:#{$/} ")
|
88
88
|
description.chomp!
|
89
89
|
@issue.mark_working!
|
90
|
-
@issue.
|
91
|
-
NewEntry.new(
|
90
|
+
@issue.save
|
91
|
+
NewEntry.new(description, @issue).execute
|
92
92
|
end
|
93
93
|
|
94
94
|
def delete_entry
|
95
95
|
id = Readline.readline('Remove task log with id : ').to_i
|
96
|
-
LogEntry.
|
96
|
+
LogEntry.delete(id)
|
97
97
|
end
|
98
98
|
|
99
99
|
# Concatenate an aggregate description to a previous item
|
100
100
|
def concat_description
|
101
101
|
id = Readline.readline("ID of task to concatenate to: ").to_i
|
102
102
|
str = Readline.readline("Information to concatenate: ").chomp
|
103
|
-
ConcatDescription.new(
|
103
|
+
ok = ConcatDescription.new(id, str).execute
|
104
|
+
puts "No such issue" if !ok
|
104
105
|
end
|
105
106
|
|
106
107
|
# Replace a pattern from a description of a log entry
|
@@ -108,84 +109,27 @@ private
|
|
108
109
|
id = Readline.readline("ID of task to perform replace: ").to_i
|
109
110
|
old_pattern = Readline.readline('replace : ').chomp
|
110
111
|
new_pattern = Readline.readline('with : ').chomp
|
111
|
-
ReplacePattern.new(
|
112
|
+
ok = ReplacePattern.new(id, old_pattern, new_pattern).execute
|
113
|
+
puts "No such task" if !ok
|
112
114
|
end
|
113
115
|
|
114
116
|
def search_term(term)
|
115
117
|
term ||= ''
|
116
118
|
term.chomp!
|
117
|
-
print_entries(LogEntry.
|
118
|
-
end
|
119
|
-
|
120
|
-
# Command comes in as edit <...>. This definition will check what comes
|
121
|
-
# next and invoke the proper method to execute.
|
122
|
-
def edit_what(terms_a)
|
123
|
-
case terms_a[0]
|
124
|
-
when /^title/
|
125
|
-
title = (terms_a.drop 1).join ' '
|
126
|
-
@issue.description = title
|
127
|
-
@issue.update
|
128
|
-
|
129
|
-
when /^desc/
|
130
|
-
long = (terms_a.drop 1).join ' '
|
131
|
-
@issue.long_description = long
|
132
|
-
@issue.update
|
133
|
-
|
134
|
-
when /^due/
|
135
|
-
date_time = terms_a.drop 1
|
136
|
-
edit_time(date_time.join(' '))
|
137
|
-
|
138
|
-
when /^reported/
|
139
|
-
date_time = terms_a.drop 1
|
140
|
-
edit_reported_time(date_time.join(' '))
|
141
|
-
|
142
|
-
else
|
143
|
-
$stdout.puts "Usage: "
|
144
|
-
$stdout.puts " edit title - to edit the title"
|
145
|
-
$stdout.puts " edit desc - to edit the long description"
|
146
|
-
$stdout.puts " edit due - to edit the due date"
|
147
|
-
$stdout.puts " edit time - to edit the time"
|
148
|
-
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# @param time is the date-time in string format (eg Oct 28)
|
153
|
-
def edit_time(time)
|
154
|
-
date_time = time_handle(time)
|
155
|
-
@issue.due_date = date_time.to_time
|
156
|
-
@issue.update
|
157
|
-
puts @strmaker.green('Updated due date')
|
158
|
-
rescue ArgumentError
|
159
|
-
$stderr.puts @strmaker.red \
|
160
|
-
"Invalid date/time format. Try format like 'Oct 28'"
|
161
|
-
end
|
162
|
-
|
163
|
-
def edit_reported_time(time_str)
|
164
|
-
date_time = time_handle(time_str)
|
165
|
-
@issue.reported_date = date_time.to_time
|
166
|
-
@issue.update
|
167
|
-
puts @strmaker.green('Updated reported date')
|
168
|
-
rescue ArgumentError
|
169
|
-
$stderr.puts @strmaker.red \
|
170
|
-
"Invalid date/time format. Try format like 'Oct 28'"
|
171
|
-
end
|
172
|
-
|
173
|
-
# TODO fix me
|
174
|
-
# @param time_str The time that we want to kind of sanitize
|
175
|
-
# @return a Time object which is set to 9am on that day if no time
|
176
|
-
# is provided
|
177
|
-
def time_handle(time_str)
|
178
|
-
date_time = DateTime.parse(time)
|
179
|
-
date_time = DateTime.parse(time + ' 9:00') if date_time.hour == 0
|
119
|
+
print_entries(LogEntry.where(["description LIKE ?", "%#{term}%"]))
|
180
120
|
end
|
181
121
|
|
182
122
|
# TODO might need refactoring
|
183
123
|
def show_entries
|
184
|
-
|
185
|
-
|
124
|
+
@issue.reload
|
125
|
+
print_entries(@issue.log_entries)
|
126
|
+
end
|
127
|
+
|
128
|
+
def print_entries(entries_a)
|
129
|
+
date_collections = entries_a.group_by{|le| le.created_at.strftime("%Y-%m-%d")}
|
186
130
|
date_collections.each_key do |date_c|
|
187
131
|
print @strmaker.green("#{date_c} - ")
|
188
|
-
print @strmaker.yellow(date_collections[date_c].first.
|
132
|
+
print @strmaker.yellow(date_collections[date_c].first.created_at.strftime("%A"))
|
189
133
|
puts " [#{@strmaker.magenta(date_collections[date_c].count.to_s)}]"
|
190
134
|
date_collections[date_c].each do |le|
|
191
135
|
puts " #{le}"
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'readline'
|
2
|
+
require 'wlog/domain/sys_config'
|
3
|
+
require 'wlog/commands/bootstrap_templates'
|
4
|
+
require 'wlog/domain/sys_config'
|
5
|
+
require 'wlog/domain/static_configurations'
|
6
|
+
|
7
|
+
module Wlog
|
8
|
+
# To list, and choose which template we want to use when making invoices.
|
9
|
+
# @author Simon Symeonidis
|
10
|
+
class TemplateUi
|
11
|
+
include StaticConfigurations
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@strmaker = SysConfig.string_decorator
|
15
|
+
# Checks for templates dir each run
|
16
|
+
BootstrapTemplates.new.execute
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
cmd = 'default'
|
21
|
+
|
22
|
+
while cmd != 'end'
|
23
|
+
cmd = Readline.readline("[#{@strmaker.green('templates')}] ").chomp
|
24
|
+
case cmd
|
25
|
+
when /^(ls|show)/ then ls
|
26
|
+
when /^set/ then set(cmd.split.drop 1)
|
27
|
+
when /^help/ then print_help
|
28
|
+
when /^end/ then next
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def print_help
|
36
|
+
['ls, show', 'list the current templates you can use',
|
37
|
+
'set <num>', 'set the template you want to use',
|
38
|
+
'help', 'print this menu'].each_with_index do |cmd,ix|
|
39
|
+
print " " if ix % 2 == 1
|
40
|
+
puts cmd
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ls
|
45
|
+
num = SysConfig.get_config('template') || 1
|
46
|
+
num = num.to_i
|
47
|
+
Dir[TemplateDir + "*"].each_with_index do |file,ix|
|
48
|
+
print " #{ix + 1 == num ? @strmaker.blue('*') : ' '} "
|
49
|
+
print "[%3d] " % (ix + 1)
|
50
|
+
puts file
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def set(rest)
|
55
|
+
num = rest[0]
|
56
|
+
unless num
|
57
|
+
puts "usage: set <number>"
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
SysConfig.store_config('template', num)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
data/lib/wlog/version.rb
CHANGED