samg-timetrap 0.1.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +7 -8
- data/VERSION.yml +3 -3
- data/lib/timetrap/cli.rb +35 -62
- data/lib/timetrap/formatters/text.rb +54 -0
- data/spec/timetrap_spec.rb +11 -6
- metadata +1 -1
data/README.md
CHANGED
@@ -101,19 +101,18 @@ Commands
|
|
101
101
|
|
102
102
|
**display**
|
103
103
|
Display a given timesheet. If no timesheet is specified, show the current
|
104
|
-
timesheet. If ``all`` is passed as
|
104
|
+
timesheet. If ``all`` is passed as SHEET display all timesheets. Accepts
|
105
105
|
an optional ``--ids`` flag which will include the entries' ids in the output.
|
106
106
|
This is useful when editing an non running entry with ``alter``.
|
107
107
|
|
108
|
-
|
108
|
+
Display is designed to support a variety of export formats that can be
|
109
|
+
specified by passing the ``--format`` flag. This currently defaults to
|
110
|
+
text. iCal output is also supported.
|
109
111
|
|
110
|
-
|
111
|
-
Export the current sheet as a comma-separated value format spreadsheet. If
|
112
|
-
the final entry is active, it is ignored.
|
113
|
-
|
114
|
-
Currently must pass 'ical' as FORMATTER
|
112
|
+
usage: ``t display [--ids] [--start DATE] [--end DATE] [--format FMT] [SHEET | all]``
|
115
113
|
|
116
|
-
|
114
|
+
**format**
|
115
|
+
Alias for display
|
117
116
|
|
118
117
|
**in**
|
119
118
|
Start the timer for the current timesheet. Must be called before out. Notes
|
data/VERSION.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
---
|
2
|
-
:patch:
|
3
|
-
:major:
|
4
|
-
:minor:
|
2
|
+
:patch: 0
|
3
|
+
:major: 1
|
4
|
+
:minor: 0
|
data/lib/timetrap/cli.rb
CHANGED
@@ -19,16 +19,14 @@ where COMMAND is one of:
|
|
19
19
|
* backend - open an sqlite shell to the database
|
20
20
|
usage: t backend
|
21
21
|
* display - display the current timesheet or a specific. Pass `all' as
|
22
|
-
|
23
|
-
usage: t display [--ids] [--start DATE] [--end DATE] [
|
22
|
+
SHEET to display all sheets.
|
23
|
+
usage: t display [--ids] [--start DATE] [--end DATE] [--format FMT] [SHEET | all]
|
24
24
|
-v, --ids Print database ids (for use with alter)
|
25
25
|
-s, --start <date:qs> Include entries that start on this date or later
|
26
26
|
-e, --end <date:qs> Include entries that start on this date or earlier
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
-s, --start <date:qs> Include entries that start on this date or later
|
31
|
-
-e, --end <date:qs> Include entries that start on this date or earlier
|
27
|
+
-f, --format <format> The output format. Currently supports ical and
|
28
|
+
text (default).
|
29
|
+
* format - alias for display
|
32
30
|
* in - start the timer for the current timesheet
|
33
31
|
usage: t in [--at TIME] [NOTES]
|
34
32
|
-a, --at <time:qs> Use this time instead of now
|
@@ -43,7 +41,7 @@ where COMMAND is one of:
|
|
43
41
|
usage: t out [--at TIME]
|
44
42
|
-a, --at <time:qs> Use this time instead of now
|
45
43
|
* running - show all running timesheets
|
46
|
-
|
44
|
+
usage: t running
|
47
45
|
* switch - switch to a new timesheet
|
48
46
|
usage: t switch TIMESHEET
|
49
47
|
|
@@ -122,72 +120,46 @@ where COMMAND is one of:
|
|
122
120
|
end
|
123
121
|
|
124
122
|
def display
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
[Timetrap.current_sheet]
|
131
|
-
end
|
132
|
-
entries = []
|
133
|
-
sheets.each do |sheet|
|
134
|
-
say "Timesheet: #{sheet}"
|
135
|
-
id_heading = args['-v'] ? 'Id' : ' '
|
136
|
-
say "#{id_heading} Day Start End Duration Notes"
|
137
|
-
last_start = nil
|
138
|
-
from_current_day = []
|
139
|
-
ee = Timetrap::Entry.filter(:sheet => sheet).order(:start)
|
140
|
-
ee = ee.filter(:start >= Date.parse(args['-s'])) if args['-s']
|
141
|
-
ee = ee.filter(:start <= Date.parse(args['-e']) + 1) if args['-e']
|
142
|
-
entries += ee.all
|
143
|
-
ee.each_with_index do |e, i|
|
144
|
-
|
145
|
-
|
146
|
-
from_current_day << e
|
147
|
-
e_end = e.end || Time.now
|
148
|
-
say "%-4s%16s%11s -%9s%10s %s" % [
|
149
|
-
(args['-v'] ? e.id : ''),
|
150
|
-
format_date_if_new(e.start, last_start),
|
151
|
-
format_time(e.start),
|
152
|
-
format_time(e.end),
|
153
|
-
format_duration(e.start, e_end),
|
154
|
-
e.note
|
155
|
-
]
|
156
|
-
|
157
|
-
nxt = ee.map[i+1]
|
158
|
-
if nxt == nil or !same_day?(e.start, nxt.start)
|
159
|
-
say "%52s" % format_total(from_current_day)
|
160
|
-
from_current_day = []
|
161
|
-
else
|
162
|
-
end
|
163
|
-
last_start = e.start
|
123
|
+
begin
|
124
|
+
fmt_klass = if args['-f']
|
125
|
+
Timetrap::Formatters.const_get("#{args['-f'].classify}")
|
126
|
+
else
|
127
|
+
Timetrap::Formatters::Text
|
164
128
|
end
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
say " Total%43s" % format_total(ee)
|
169
|
-
say "\n" unless sheet == sheets.last
|
129
|
+
rescue
|
130
|
+
say "Invalid format specified `#{args['-f']}'"
|
131
|
+
return
|
170
132
|
end
|
171
|
-
if
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
133
|
+
ee = if (sheet = sheet_name_from_string(unused_args)) == 'all'
|
134
|
+
Timetrap::Entry
|
135
|
+
elsif sheet =~ /.+/
|
136
|
+
Timetrap::Entry.filter(:sheet => sheet)
|
137
|
+
else
|
138
|
+
Timetrap::Entry.filter(:sheet => Timetrap.current_sheet)
|
176
139
|
end
|
140
|
+
ee = ee.filter(:start >= Date.parse(args['-s'])) if args['-s']
|
141
|
+
ee = ee.filter(:start <= Date.parse(args['-e']) + 1) if args['-e']
|
142
|
+
say Timetrap.format(fmt_klass, ee.order(:start).all)
|
177
143
|
end
|
178
144
|
|
179
145
|
# TODO: Consolidate display and format
|
180
146
|
def format
|
181
147
|
begin
|
182
|
-
fmt_klass = Timetrap::Formatters.const_get("#{
|
148
|
+
fmt_klass = Timetrap::Formatters.const_get("#{args['-f'].classify}")
|
183
149
|
rescue
|
184
|
-
say "Invalid format specified `#{
|
150
|
+
say "Invalid format specified `#{args['-f']}'"
|
185
151
|
return
|
186
152
|
end
|
187
|
-
ee =
|
153
|
+
ee = if (sheet = sheet_name_from_string(unused_args)) == 'all'
|
154
|
+
Timetrap::Entry
|
155
|
+
elsif sheet =~ /.+/
|
156
|
+
Timetrap::Entry.filter(:sheet => sheet)
|
157
|
+
else
|
158
|
+
Timetrap::Entry.filter(:sheet => Timetrap.current_sheet)
|
159
|
+
end
|
188
160
|
ee = ee.filter(:start >= Date.parse(args['-s'])) if args['-s']
|
189
161
|
ee = ee.filter(:start <= Date.parse(args['-e']) + 1) if args['-e']
|
190
|
-
say Timetrap.format(fmt_klass,ee.all)
|
162
|
+
say Timetrap.format(fmt_klass, ee.all)
|
191
163
|
end
|
192
164
|
|
193
165
|
def switch
|
@@ -231,7 +203,8 @@ where COMMAND is one of:
|
|
231
203
|
end
|
232
204
|
|
233
205
|
def running
|
234
|
-
say "
|
206
|
+
say "Running Timesheets:"
|
207
|
+
say Timetrap::Entry.filter(:end => nil).map{|e| " #{e.sheet}: #{e.note}"}.uniq.sort
|
235
208
|
end
|
236
209
|
|
237
210
|
private
|
@@ -1 +1,55 @@
|
|
1
|
+
module Timetrap
|
2
|
+
module Formatters
|
3
|
+
class Text
|
4
|
+
attr_accessor :output
|
5
|
+
include Timetrap::Helpers
|
1
6
|
|
7
|
+
def initialize entries
|
8
|
+
self.output = ''
|
9
|
+
sheets = entries.inject({}) do |h, e|
|
10
|
+
h[e.sheet] ||= []
|
11
|
+
h[e.sheet] << e
|
12
|
+
h
|
13
|
+
end
|
14
|
+
(sheet_names = sheets.keys.sort).each do |sheet|
|
15
|
+
self.output << "Timesheet: #{sheet}\n"
|
16
|
+
id_heading = Timetrap::CLI.args['-v'] ? 'Id' : ' '
|
17
|
+
self.output << "#{id_heading} Day Start End Duration Notes\n"
|
18
|
+
last_start = nil
|
19
|
+
from_current_day = []
|
20
|
+
sheets[sheet].each_with_index do |e, i|
|
21
|
+
from_current_day << e
|
22
|
+
e_end = e.end || Time.now
|
23
|
+
self.output << "%-4s%16s%11s -%9s%10s %s\n" % [
|
24
|
+
(Timetrap::CLI.args['-v'] ? e.id : ''),
|
25
|
+
format_date_if_new(e.start, last_start),
|
26
|
+
format_time(e.start),
|
27
|
+
format_time(e.end),
|
28
|
+
format_duration(e.start, e_end),
|
29
|
+
e.note
|
30
|
+
]
|
31
|
+
|
32
|
+
nxt = sheets[sheet].map[i+1]
|
33
|
+
if nxt == nil or !same_day?(e.start, nxt.start)
|
34
|
+
self.output << "%52s\n" % format_total(from_current_day)
|
35
|
+
from_current_day = []
|
36
|
+
else
|
37
|
+
end
|
38
|
+
last_start = e.start
|
39
|
+
end
|
40
|
+
self.output << <<-OUT
|
41
|
+
---------------------------------------------------------
|
42
|
+
OUT
|
43
|
+
self.output << " Total%43s\n" % format_total(sheets[sheet])
|
44
|
+
self.output << "\n" unless sheet == sheet_names.last
|
45
|
+
end
|
46
|
+
if sheets.size > 1
|
47
|
+
self.output << <<-OUT
|
48
|
+
-------------------------------------------------------------
|
49
|
+
OUT
|
50
|
+
self.output << "Grand Total%41s\n" % format_total(sheets.values.flatten)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/timetrap_spec.rb
CHANGED
@@ -171,17 +171,17 @@ Grand Total 10:00:00
|
|
171
171
|
end
|
172
172
|
|
173
173
|
it "should filter events by the passed dates" do
|
174
|
-
invoke 'format ical --start 2008-10-03 --end 2008-10-03'
|
174
|
+
invoke 'format --format ical --start 2008-10-03 --end 2008-10-03'
|
175
175
|
$stdout.string.scan(/BEGIN:VEVENT/).should have(1).item
|
176
176
|
end
|
177
177
|
|
178
178
|
it "should not filter events by date when none are passed" do
|
179
|
-
invoke 'format ical'
|
179
|
+
invoke 'format --format ical'
|
180
180
|
$stdout.string.scan(/BEGIN:VEVENT/).should have(2).item
|
181
181
|
end
|
182
182
|
|
183
183
|
it "should export a sheet to an ical format" do
|
184
|
-
invoke 'format ical --start 2008-10-03 --end 2008-10-03'
|
184
|
+
invoke 'format --format ical --start 2008-10-03 --end 2008-10-03'
|
185
185
|
desired = <<-EOF
|
186
186
|
BEGIN:VCALENDAR
|
187
187
|
VERSION:2.0
|
@@ -347,12 +347,16 @@ current sheet: 0:01:00 (a timesheet that is running)
|
|
347
347
|
end
|
348
348
|
|
349
349
|
describe "running" do
|
350
|
-
|
350
|
+
it "should show all running timesheets" do
|
351
351
|
create_entry :sheet => 'one', :end => nil
|
352
352
|
create_entry :sheet => 'two', :end => nil
|
353
|
+
create_entry :sheet => 'three'
|
354
|
+
invoke 'running'
|
355
|
+
$stdout.string.should == "Running Timesheets:\n one: note\n two: note\n"
|
353
356
|
end
|
354
|
-
it "should show
|
355
|
-
|
357
|
+
it "should show no runnig timesheets" do
|
358
|
+
invoke 'running'
|
359
|
+
$stdout.string.should == "Running Timesheets:\n"
|
356
360
|
end
|
357
361
|
end
|
358
362
|
|
@@ -444,6 +448,7 @@ current sheet: 0:01:00 (a timesheet that is running)
|
|
444
448
|
Timetrap.current_sheet.should == 'sheet2'
|
445
449
|
end
|
446
450
|
end
|
451
|
+
|
447
452
|
end
|
448
453
|
|
449
454
|
describe Timetrap::Entry do
|