@@ -1,8 +1,5 @@ | |||
class Tisk::Commands::ClockList < Tisk::Command | |||
############################################################################## | |||
TIME_FORMAT = '[%Y-%m-%d %H:%M]' | |||
############################################################################## | |||
description("list clock entries for a ticket") | |||
@@ -43,35 +40,7 @@ class Tisk::Commands::ClockList < Tisk::Command | |||
card.entries.each_with_index do |entry, index| | |||
next if !options.all and !entry.from_day?(options.day) | |||
format(entry, index) | |||
end | |||
end | |||
############################################################################## | |||
private | |||
############################################################################## | |||
def format (entry, index) | |||
output = (index + 1).to_s.rjust(3, ' ') + ') ' | |||
status = | |||
if !entry.stop | |||
'running' | |||
elsif entry.approved? | |||
'approved' | |||
else | |||
'pending' | |||
end | |||
output << status.ljust(9, ' ') | |||
output << entry.start.strftime(TIME_FORMAT) + '--' | |||
output << (entry.stop || Time.now).strftime(TIME_FORMAT) | |||
if entry.stop | |||
output << ' => ' | |||
output << Tisk::Clock::Format.duration(entry.duration) | |||
$stdout.puts(Tisk::Clock::Format.entry(entry, index)) | |||
end | |||
$stdout.puts(output) | |||
end | |||
end |
@@ -0,0 +1,85 @@ | |||
class Tisk::Commands::ClockUpdate < Tisk::Command | |||
############################################################################## | |||
description("update clock entries for a ticket") | |||
############################################################################## | |||
def self.name | |||
"update" | |||
end | |||
############################################################################## | |||
parse_command_line do | |||
options.approve = false | |||
options.reject = false | |||
options.start = nil | |||
options.stop = nil | |||
options.duration = nil | |||
@parser.banner = 'Usage: tisk clock update [options] ticket-id entry-id' | |||
@parser.on('-a', '--approve', 'Approve the entry') do |a| | |||
options.approve = a | |||
end | |||
@parser.on('-r', '--reject', 'Remove approved flag') do |r| | |||
options.reject = r | |||
end | |||
@parser.on('-s', '--start=TIME', 'Set start date and time to TIME') do |t| | |||
options.start = Time.parse(t) | |||
end | |||
@parser.on('-e', '--stop=TIME', 'Set stop date and time to TIME') do |t| | |||
options.stop = Time.parse(t) | |||
end | |||
@parser.on('-d', '--duration=X', 'Set duration to X') do |d| | |||
options.duration = d | |||
end | |||
end | |||
############################################################################## | |||
def run | |||
raise("please give a ticket ID and entry ID") if argv.size != 2 | |||
spools = selected_spool_or_all_spools | |||
search = Tisk::Search.new(config, spools) | |||
matches = search.find_by_id(argv.first) | |||
raise("no such ticket: #{argv.first}") if matches.size.zero? | |||
raise("ticket ID matches more than one ticket") if matches.size > 1 | |||
ticket = Tisk::Ticket.new(matches[0][1]) | |||
card = Tisk::Clock::TimeCard.new(ticket) | |||
entry = card.entries[argv.last.to_i - 1] | |||
raise("no such entry: #{argv.last} in ticket: #{argv.first}") if entry.nil? | |||
entry.approved = false if options.reject | |||
entry.approved = true if options.approve | |||
entry.start = options.start if options.start | |||
entry.stop = options.stop if options.stop | |||
if options.duration | |||
if m = options.duration.match(/^\s*(\d+):(\d+)\s*$/) | |||
entry.stop = entry.start + | |||
(m[1].to_i * 3600) + (m[2].to_i * 60) | |||
elsif m = options.duration.match(/^\s*(\d+(?:\.\d+)?)([hm]?)\s*$/i) | |||
value = | |||
case m[2] | |||
when 'h', 'H' then m[1].to_f * 3600.0 | |||
when 'm', 'M' then m[1].to_f * 60.0 | |||
else m[1].to_f * 60.0 | |||
end | |||
entry.stop = entry.start + value | |||
else | |||
raise("unknown duration format: #{options.duration}") | |||
end | |||
end | |||
card.write! | |||
$stdout.puts(Tisk::Clock::Format.entry(entry, argv.last.to_i)) | |||
end | |||
end |
@@ -1,5 +1,8 @@ | |||
module Tisk::Clock::Format | |||
############################################################################## | |||
ENTRY_TIME_FORMAT = '[%Y-%m-%d %H:%M]' | |||
############################################################################## | |||
def self.duration (duration) | |||
minutes = seconds_to_minutes(duration) | |||
@@ -44,4 +47,29 @@ module Tisk::Clock::Format | |||
duration = self.duration(stop - start) | |||
"[#{duration}] #{t.short_id} #{t.subject}" | |||
end | |||
############################################################################## | |||
def self.entry (entry, index) | |||
output = (index + 1).to_s.rjust(3, ' ') + ') ' | |||
status = | |||
if !entry.stop | |||
'running' | |||
elsif entry.approved? | |||
'approved' | |||
else | |||
'pending' | |||
end | |||
output << status.ljust(9, ' ') | |||
output << entry.start.strftime(ENTRY_TIME_FORMAT) + '--' | |||
output << (entry.stop || Time.now).strftime(ENTRY_TIME_FORMAT) | |||
if entry.stop | |||
output << ' => ' | |||
output << Tisk::Clock::Format.duration(entry.duration) | |||
end | |||
output | |||
end | |||
end |
@@ -69,9 +69,10 @@ class Tisk::Clock::Report | |||
record.approved = record.entries.all? {|e| e.approved?} | |||
record.running = record.entries.any? {|e| e.stop.nil?} | |||
record.flags = | |||
if record.running then 'r' | |||
if record.running then 'r' | |||
elsif record.approved then 'a' | |||
else '-' end | |||
else 'p' | |||
end | |||
end | |||
end | |||
@@ -34,6 +34,12 @@ class Tisk::Clock::TimeCard | |||
entry | |||
end | |||
############################################################################## | |||
def write! | |||
save | |||
@ticket.write! | |||
end | |||
############################################################################## | |||
def entries_between (start_time, stop_time) | |||
@entries.select do |entry| |