slimtimercli 0.1.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.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +21 -0
- data/README.txt +37 -0
- data/Rakefile +4 -0
- data/bin/slimtimer +12 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +15 -0
- data/lib/slimtimercli/entities.rb +71 -0
- data/lib/slimtimercli/slim_timer.rb +139 -0
- data/lib/slimtimercli/version.rb +9 -0
- data/lib/slimtimercli.rb +215 -0
- data/log/debug.log +0 -0
- data/setup.rb +1585 -0
- data/spec/slimtimercli_spec.rb +50 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- metadata +78 -0
data/History.txt
ADDED
data/License.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 FIXME full name
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
bin/slimtimer
|
7
|
+
config/hoe.rb
|
8
|
+
config/requirements.rb
|
9
|
+
lib/slimtimercli.rb
|
10
|
+
lib/slimtimercli/entities.rb
|
11
|
+
lib/slimtimercli/slim_timer.rb
|
12
|
+
lib/slimtimercli/version.rb
|
13
|
+
log/debug.log
|
14
|
+
setup.rb
|
15
|
+
spec/slimtimercli_spec.rb
|
16
|
+
spec/spec.opts
|
17
|
+
spec/spec_helper.rb
|
18
|
+
tasks/deployment.rake
|
19
|
+
tasks/environment.rake
|
20
|
+
tasks/rspec.rake
|
21
|
+
tasks/website.rake
|
data/README.txt
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
= slimtimercli
|
2
|
+
|
3
|
+
== DESCRIPTION:
|
4
|
+
|
5
|
+
SlimTimer is a tool to record your time spend on a
|
6
|
+
task. SlimTimer CLI allows you to controll your
|
7
|
+
SlimTimer directly from where you spend most of your
|
8
|
+
time - on the command line. To use SlimTimer proceed
|
9
|
+
with the following steps:
|
10
|
+
|
11
|
+
The first time you need to setup SlimTimer CLI with
|
12
|
+
|
13
|
+
slimtimer setup
|
14
|
+
|
15
|
+
Now it will ask for your email and password and API key
|
16
|
+
to use with your account. These information will be stored
|
17
|
+
in ~/.slimtimer/config.yml
|
18
|
+
|
19
|
+
To create a task run
|
20
|
+
|
21
|
+
slimtimer create_task my_shiny_task
|
22
|
+
|
23
|
+
To spend some time on the task you have to make the timer run
|
24
|
+
|
25
|
+
slimtimer start my_shiny_task
|
26
|
+
|
27
|
+
When you finished working on a task, you can call
|
28
|
+
|
29
|
+
slimtimer end
|
30
|
+
|
31
|
+
This will write the time spend back to SlimTimer.com.
|
32
|
+
Finally you can run
|
33
|
+
|
34
|
+
slimtimer tasks
|
35
|
+
|
36
|
+
To show all your tasks available.
|
37
|
+
|
data/Rakefile
ADDED
data/bin/slimtimer
ADDED
data/config/hoe.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'slimtimercli/version'
|
2
|
+
|
3
|
+
AUTHOR = 'Martin Grund' # can also be an array of Authors
|
4
|
+
EMAIL = "grundprinzip@gmail.com"
|
5
|
+
DESCRIPTION = "Command line interface to SlimTimer"
|
6
|
+
GEM_NAME = 'slimtimercli' # what ppl will type to install your gem
|
7
|
+
RUBYFORGE_PROJECT = 'rug-b' # The unix name for your project
|
8
|
+
HOMEPATH = "http://blog.grundprinzip.de"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
10
|
+
|
11
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
12
|
+
@config = nil
|
13
|
+
RUBYFORGE_USERNAME = "unknown"
|
14
|
+
def rubyforge_username
|
15
|
+
unless @config
|
16
|
+
begin
|
17
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
18
|
+
rescue
|
19
|
+
puts <<-EOS
|
20
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
21
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
22
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
23
|
+
EOS
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
REV = nil
|
32
|
+
# UNCOMMENT IF REQUIRED:
|
33
|
+
# REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
|
34
|
+
VERS = Slimtimercli::VERSION::STRING + (REV ? ".#{REV}" : "")
|
35
|
+
RDOC_OPTS = ['--quiet', '--title', 'slimtimercli documentation',
|
36
|
+
"--opname", "index.html",
|
37
|
+
"--line-numbers",
|
38
|
+
"--main", "README",
|
39
|
+
"--inline-source"]
|
40
|
+
|
41
|
+
class Hoe
|
42
|
+
def extra_deps
|
43
|
+
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
|
44
|
+
@extra_deps
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Generate all the Rake tasks
|
49
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
50
|
+
$hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
51
|
+
p.developer(AUTHOR, EMAIL)
|
52
|
+
p.description = DESCRIPTION
|
53
|
+
p.summary = DESCRIPTION
|
54
|
+
p.url = HOMEPATH
|
55
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
56
|
+
p.test_globs = ["test/**/test_*.rb"]
|
57
|
+
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
58
|
+
|
59
|
+
# == Optional
|
60
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
61
|
+
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
62
|
+
|
63
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
|
68
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
69
|
+
$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
70
|
+
$hoe.rsync_args = '-av --delete --ignore-errors'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
%w[rake hoe newgem rubigen].each do |req_gem|
|
6
|
+
begin
|
7
|
+
require req_gem
|
8
|
+
rescue LoadError
|
9
|
+
puts "This Rakefile requires the '#{req_gem}' RubyGem."
|
10
|
+
puts "Installation: gem install #{req_gem} -y"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class TimeEntry
|
2
|
+
attr_accessor :id, :start_time, :end_time,
|
3
|
+
:duration_in_seconds, :tags, :in_progress, :updated_at,
|
4
|
+
:created_at, :task
|
5
|
+
|
6
|
+
def self._load(hsh)
|
7
|
+
te = TimeEntry.new
|
8
|
+
hsh.each {|k,v|
|
9
|
+
te.__send__("#{k}=".to_sym, v) if te.respond_to?("#{k}=".to_sym)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def _serialize
|
14
|
+
{"time_entry" => {
|
15
|
+
"start_time" => @start_time,
|
16
|
+
"duration_in_seconds" => @duration_in_seconds,
|
17
|
+
"task_id" => @task.id}}
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class Task
|
23
|
+
attr_accessor :name, :tags, :role, :owners, :hours,
|
24
|
+
:id
|
25
|
+
|
26
|
+
def self._load(hsh)
|
27
|
+
Task.new.__send__(:_load, hsh)
|
28
|
+
end
|
29
|
+
|
30
|
+
def _serialize
|
31
|
+
{"task" => instance_variables.map{ |i|
|
32
|
+
{i.to_s.gsub("@", "") => instance_variable_get(i)}
|
33
|
+
}.inject({}){|m,v| m.merge v}}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def _load(hsh)
|
39
|
+
hsh.each do |k,v|
|
40
|
+
self.instance_variable_set("@#{k}", v) if self.respond_to?(k.to_sym) &&
|
41
|
+
!v.kind_of?(Array)
|
42
|
+
end
|
43
|
+
|
44
|
+
@owners = hsh["owners"].map{|o| User._load(o)}
|
45
|
+
@coworkers = hsh["coworkers"].map{|o| User._load(o)}
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
class User
|
53
|
+
attr_accessor :email, :password, :user_id, :name
|
54
|
+
|
55
|
+
def initialize(e=nil, p=nil)
|
56
|
+
@email = e
|
57
|
+
@password = p
|
58
|
+
end
|
59
|
+
|
60
|
+
def self._load(hsh)
|
61
|
+
u = User.new
|
62
|
+
hsh.each do |k,v|
|
63
|
+
u.send("#{k}=".to_sym, v) if u.respond_to?("#{k}=".to_sym)
|
64
|
+
end
|
65
|
+
u
|
66
|
+
end
|
67
|
+
|
68
|
+
def _serialize
|
69
|
+
{"user" => {"email" => email, "password" => password}}
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
class SlimTimer
|
2
|
+
|
3
|
+
DATE_FORMAT = "%Y-%m-%d %H-%M-%S"
|
4
|
+
|
5
|
+
@@host = "slimtimer.com"
|
6
|
+
@@port = 80
|
7
|
+
#@@api_key = ""
|
8
|
+
|
9
|
+
attr_accessor :tasks, :time_entries
|
10
|
+
|
11
|
+
def initialize(user, pass, api)
|
12
|
+
@user = user; @pass = pass
|
13
|
+
@api_key = api
|
14
|
+
end
|
15
|
+
|
16
|
+
# Performs the login to the system, and stores
|
17
|
+
# the user id and the access token in the local
|
18
|
+
# class for reusse
|
19
|
+
def login
|
20
|
+
data = post_request("/users/token", User.new(@user, @pass)._serialize)
|
21
|
+
@token = data["access_token"]
|
22
|
+
@user_id = data["user_id"]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Lists all tasks for the user logged in the system
|
26
|
+
# ==== Parameters
|
27
|
+
# show_completed<String>:: yes | no | only Include completed tasks (yes/no)
|
28
|
+
# or show only completed tasks Default: yes
|
29
|
+
# role<String>:: owner,coworker,reporter Include tasks where the user's role
|
30
|
+
# is one of the roles given (comma delimited) Default:
|
31
|
+
# owner,coworker
|
32
|
+
def tasks(show_completed = "yes", role="owner,coworker")
|
33
|
+
list = get_request("/users/#{@user_id}/tasks",
|
34
|
+
{"show_completed" => show_completed,
|
35
|
+
"role" => role})
|
36
|
+
|
37
|
+
list.map{ |t|
|
38
|
+
Task._load(t)
|
39
|
+
}
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
# Create a new task for this user
|
44
|
+
# ==== Parameters
|
45
|
+
# name<String>:: name for the new task
|
46
|
+
# tags<String>:: comma separated list of tags for the task
|
47
|
+
def create_task(name, tags= "", coworker_emails = "", reporter_emails = "")
|
48
|
+
|
49
|
+
t = Task.new
|
50
|
+
t.name = name
|
51
|
+
t.tags = tags
|
52
|
+
|
53
|
+
t._serialize
|
54
|
+
|
55
|
+
|
56
|
+
Task._load(post_request("/users/#{@user_id}/tasks", t._serialize))
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_task_by_name(name)
|
60
|
+
tasks("no").find {|t| t.name == name}
|
61
|
+
end
|
62
|
+
|
63
|
+
def delete_task(name)
|
64
|
+
t = find_task_by_name(name)
|
65
|
+
delete_request("/users/#{@user_id}/tasks/#{t.id}")
|
66
|
+
end
|
67
|
+
|
68
|
+
# List all time entries for the user logged in
|
69
|
+
# ==== Parameters
|
70
|
+
# range_start<Time>:: start of the range
|
71
|
+
# range_end<Time>:: end of the range
|
72
|
+
def time_entries(range_start = nil, range_end = nil)
|
73
|
+
options = {}
|
74
|
+
|
75
|
+
options = {"range_start" =>
|
76
|
+
range_start.strftime(DATE_FORMAT)} if range_start
|
77
|
+
options = {"range_end" =>
|
78
|
+
range_end.strftime(DATE_FORMAT)} if range_end
|
79
|
+
|
80
|
+
# do the actual request
|
81
|
+
get_request("/users/#{@user_id}/time_entries", options)
|
82
|
+
end
|
83
|
+
|
84
|
+
def create_time_entry(task, start_time = Time.now, duration = 0)
|
85
|
+
te = TimeEntry.new
|
86
|
+
te.task = task; te.start_time = start_time
|
87
|
+
te.duration_in_seconds = duration
|
88
|
+
|
89
|
+
post_request("/users/#{@user_id}/time_entries", te._serialize)
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
def handle_error(object)
|
95
|
+
if object.kind_of?(ActiveRecord::Errors)
|
96
|
+
raise "ActiveRecord::Errors " + object.map{|k,v| k + " " + v}.join("\n")
|
97
|
+
else
|
98
|
+
object
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_request(path, params = {})
|
103
|
+
post_request(path, {"_method" => "get"}.merge(params))
|
104
|
+
end
|
105
|
+
|
106
|
+
def put_request(path, params = {})
|
107
|
+
post_request(path, {"_method" => "put"}.merge(params))
|
108
|
+
end
|
109
|
+
|
110
|
+
def delete_request(path, params = {})
|
111
|
+
post_request(path, {"_method" => "delete"}.merge(params))
|
112
|
+
end
|
113
|
+
|
114
|
+
def post_request(path, params = {})
|
115
|
+
request(Net::HTTP::Post.new(path, default_header), params)
|
116
|
+
end
|
117
|
+
|
118
|
+
def request(method, params = {})
|
119
|
+
|
120
|
+
puts "Start Request" if $DEBUG
|
121
|
+
# merge api key
|
122
|
+
params = {"api_key" => @api_key}.merge(params)
|
123
|
+
# If token there merge it
|
124
|
+
params = {"access_token" => @token}.merge(params) if @token
|
125
|
+
res, body = Net::HTTP.start(@@host,@@port) {|http|
|
126
|
+
p params if $DEBUG
|
127
|
+
method.body = params.to_yaml
|
128
|
+
http.request(method)
|
129
|
+
}
|
130
|
+
puts "Finished Request" if $DEBUG
|
131
|
+
handle_error(YAML.load(body))
|
132
|
+
end
|
133
|
+
|
134
|
+
def default_header
|
135
|
+
{"Accept" => "application/x-yaml",
|
136
|
+
"Content-Type" => "application/x-yaml"}
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
data/lib/slimtimercli.rb
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
require 'net/http'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'active_record'
|
8
|
+
require 'active_support'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
require "slimtimercli/entities"
|
12
|
+
require "slimtimercli/slim_timer"
|
13
|
+
require "slimtimercli/version"
|
14
|
+
|
15
|
+
module Slimtimercli
|
16
|
+
module Helper
|
17
|
+
def self.login
|
18
|
+
config = Helper::load_config
|
19
|
+
st = SlimTimer.new(config["email"], config["password"],
|
20
|
+
config["api_key"])
|
21
|
+
st.login
|
22
|
+
|
23
|
+
st
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.root
|
27
|
+
File.join(ENV["HOME"], ".slimtimer")
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.config_file
|
31
|
+
File.join(root, "config.yml")
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.tasks_file
|
35
|
+
File.join(root, "tasks.yml")
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.current_file
|
39
|
+
File.join(root, "current.yml")
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.check_and_create_dir
|
43
|
+
raise "Home DIR not set!" unless ENV["HOME"]
|
44
|
+
|
45
|
+
unless File.directory?(root)
|
46
|
+
FileUtils.mkdir(root)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.load_config
|
51
|
+
check_and_create_dir
|
52
|
+
|
53
|
+
unless File.exists?(File.join(root, "config.yml"))
|
54
|
+
File.open( File.join(root, "config.yml"), 'w' ) do |out|
|
55
|
+
YAML.dump({}, out )
|
56
|
+
end
|
57
|
+
end
|
58
|
+
load_file("config.yml")
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.save_config(config)
|
62
|
+
dump_to_file(config, "config.yml")
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.load_file(file)
|
66
|
+
File.open( File.join(root, file) ) { |yf| YAML::load( yf ) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.dump_to_file(object, file)
|
70
|
+
check_and_create_dir
|
71
|
+
File.open( File.join(root, file), 'w' ) do |out|
|
72
|
+
YAML.dump(object, out )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.create_task
|
78
|
+
name = ARGV[1]
|
79
|
+
|
80
|
+
st = Helper::login
|
81
|
+
if st.create_task(name)
|
82
|
+
Helper::dump_to_file(st.tasks, "tasks.yml")
|
83
|
+
puts "Task #{name} successfully created."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.tasks(show= true)
|
88
|
+
config = Helper::load_config
|
89
|
+
st = SlimTimer.new(config["email"], config["password"],
|
90
|
+
config["api_key"])
|
91
|
+
|
92
|
+
if !File.exists?(Helper::tasks_file) ||
|
93
|
+
File.mtime(Helper::tasks_file) < (Time.now - 60 * 60 *24)
|
94
|
+
|
95
|
+
st.login
|
96
|
+
Helper::dump_to_file(st.tasks, "tasks.yml")
|
97
|
+
end
|
98
|
+
|
99
|
+
tasks = Helper::load_file("tasks.yml")
|
100
|
+
|
101
|
+
return tasks unless show
|
102
|
+
|
103
|
+
tasks.each do |t|
|
104
|
+
puts t.name
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.force_reload
|
109
|
+
config = Helper::load_config
|
110
|
+
st = SlimTimer.new(config["email"], config["password"],
|
111
|
+
config["api_key"])
|
112
|
+
|
113
|
+
st.login
|
114
|
+
Helper::dump_to_file(st.tasks, "tasks.yml")
|
115
|
+
tasks = Helper::load_file("tasks.yml")
|
116
|
+
|
117
|
+
tasks.each do |t|
|
118
|
+
puts t.name
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# This method stores the credentials in the necessary directoyr
|
123
|
+
def self.setup
|
124
|
+
config = Helper::load_config
|
125
|
+
|
126
|
+
puts "Slimtimer Login Credentials\n"
|
127
|
+
print "E-Mail: "
|
128
|
+
config["email"] = STDIN.gets.gsub("\n", "")
|
129
|
+
|
130
|
+
print "Password: "
|
131
|
+
config["password"] = STDIN.gets.gsub("\n", "")
|
132
|
+
|
133
|
+
print "API Key: "
|
134
|
+
config["api_key"] = STDIN.gets.gsub("\n", "")
|
135
|
+
|
136
|
+
Helper::save_config(config)
|
137
|
+
|
138
|
+
# clear the screen
|
139
|
+
system("clear")
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.help
|
143
|
+
puts <<-HELP
|
144
|
+
SlimTimer is a tool to record your time spend on a
|
145
|
+
task. SlimTimer CLI allows you to controll your
|
146
|
+
SlimTimer directly from where you spend most of your
|
147
|
+
time - on the command line. To use SlimTimer proceed
|
148
|
+
with the following steps:
|
149
|
+
|
150
|
+
The first time you need to setup SlimTimer CLI with
|
151
|
+
|
152
|
+
slimtimer setup
|
153
|
+
|
154
|
+
Now it will ask for your email and password and API key
|
155
|
+
to use with your account. These information will be stored
|
156
|
+
in ~/.slimtimer/config.yml
|
157
|
+
|
158
|
+
To create a task run
|
159
|
+
|
160
|
+
slimtimer create_task my_shiny_task
|
161
|
+
|
162
|
+
To spend some time on the task you have to make the timer run
|
163
|
+
|
164
|
+
slimtimer start my_shiny_task
|
165
|
+
|
166
|
+
When you finished working on a task, you can call
|
167
|
+
|
168
|
+
slimtimer end
|
169
|
+
|
170
|
+
This will write the time spend back to SlimTimer.com.
|
171
|
+
Finally you can run
|
172
|
+
|
173
|
+
slimtimer tasks
|
174
|
+
|
175
|
+
To show all your tasks available.
|
176
|
+
HELP
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.start
|
180
|
+
info = {"task" => ARGV[1],
|
181
|
+
"start_time" => Time.now}
|
182
|
+
|
183
|
+
# dum curent task to file
|
184
|
+
Helper::dump_to_file(info, "current.yml")
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.end
|
188
|
+
begin
|
189
|
+
info = Helper::load_file("current.yml")
|
190
|
+
rescue
|
191
|
+
puts "You must start a task before you finish it"
|
192
|
+
return
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
#Find task in tasks yml
|
197
|
+
t = tasks(false).find {|t| t.name == info["task"]}
|
198
|
+
|
199
|
+
raise "Task not found in list. Reload List?" unless t
|
200
|
+
|
201
|
+
st = Helper::login
|
202
|
+
result = st.create_time_entry(t, info["start_time"],
|
203
|
+
(Time.now - info["start_time"]).to_i)
|
204
|
+
|
205
|
+
# Delete yml file
|
206
|
+
if result
|
207
|
+
FileUtils.rm(Helper::current_file)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Output
|
211
|
+
puts "Wrote new Entry for #{t.name}, duration #{result["duration_in_seconds"] / 60}m"
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
data/log/debug.log
ADDED
File without changes
|