v2gpti 1.3.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config_template +0 -3
- data/lib/git-pivotal-tracker-integration.rb +0 -2
- data/lib/git-pivotal-tracker-integration/command/base.rb +1 -63
- data/lib/git-pivotal-tracker-integration/command/configuration.rb +0 -8
- data/lib/git-pivotal-tracker-integration/command/finish.rb +0 -10
- metadata +18 -19
- data/lib/git-pivotal-tracker-integration/util/togglV8.rb +0 -438
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a09e57e80af81a45583c28e77abbbd0077152f7
|
4
|
+
data.tar.gz: 9755fa1d0100286f3861264260d55d044b2fc910
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fa6335e4af27e4d660d90e968ee36fe1ed795e5cd34e632c8d5c7015fc71478e5ed30a04601b52a633ef98efbda6ce9da0b890916808bac6704003460e8e5a0
|
7
|
+
data.tar.gz: 0fa9f32ee10a80862d8680793b4d4da7e95d86ef7a171b117f5b572cbdfc49f92051428e4840d45463c0faa080487182458dfa61e39f4e043246c5ee1e10d1a8
|
data/config_template
CHANGED
@@ -37,7 +37,6 @@ module GitPivotalTrackerIntegration
|
|
37
37
|
end
|
38
38
|
|
39
39
|
@repository_root = Util::Git.repository_root
|
40
|
-
@toggl = Toggl.new
|
41
40
|
@configuration = Command::Configuration.new
|
42
41
|
|
43
42
|
@configuration.check_for_config_file
|
@@ -58,28 +57,6 @@ module GitPivotalTrackerIntegration
|
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
|
-
def finish_toggle(configuration, time_spent)
|
62
|
-
current_story = @configuration.story(@project)
|
63
|
-
|
64
|
-
# If a story gets rejected and the developer works on it, then we need to check if the task is already created or not.
|
65
|
-
params = parameters(configuration, time_spent)
|
66
|
-
if params[:tid].nil?
|
67
|
-
begin
|
68
|
-
@toggl.create_task(params)
|
69
|
-
rescue StandardError => te
|
70
|
-
$LOG.error(te.backtrace.join("\n\t"))
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
#If for some reason time entry cannot be done, then catch exception and continue.
|
75
|
-
begin
|
76
|
-
@toggl.create_time_entry(params)
|
77
|
-
rescue StandardError => te
|
78
|
-
$LOG.error(te.backtrace.join("\n\t"))
|
79
|
-
puts "Unable to log the time."
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
60
|
def start_logging
|
84
61
|
$LOG = Logger.new("#{logger_filename}", 'weekly')
|
85
62
|
end
|
@@ -111,46 +88,7 @@ module GitPivotalTrackerIntegration
|
|
111
88
|
raise NotImplementedError
|
112
89
|
end
|
113
90
|
|
114
|
-
|
115
|
-
# name : The name of the task (string, required, unique in project)
|
116
|
-
# pid : project ID for the task (integer, required)
|
117
|
-
# wid : workspace ID, where the task will be saved (integer, project's workspace id is used when not supplied)
|
118
|
-
# uid : user ID, to whom the task is assigned to (integer, not required)
|
119
|
-
# estimated_seconds : estimated duration of task in seconds (integer, not required)
|
120
|
-
# active : whether the task is done or not (boolean, by default true)
|
121
|
-
# at : timestamp that is sent in the response for PUT, indicates the time task was last updated
|
122
|
-
# -- Additional fields --
|
123
|
-
# done_seconds : duration (in seconds) of all the time entries registered for this task
|
124
|
-
# uname : full name of the person to whom the task is assigned to
|
125
|
-
TIMER_TOKENS = {
|
126
|
-
"m" => (60),
|
127
|
-
"h" => (60 * 60),
|
128
|
-
"d" => (60 * 60 * 8) # a work day is 8 hours
|
129
|
-
}
|
130
|
-
def parameters(configuration, time_spent)
|
131
|
-
current_story = configuration.story(@project)
|
132
|
-
params = Hash.new
|
133
|
-
params[:name] = "#{current_story.id}" + " - " + "#{current_story.name}"
|
134
|
-
params[:estimated_seconds] = estimated_seconds current_story
|
135
|
-
params[:pid] = configuration.toggl_project_id
|
136
|
-
params[:uid] = @toggl.me["id"]
|
137
|
-
params[:tags] = [current_story.story_type]
|
138
|
-
params[:active] = false
|
139
|
-
params[:description] = "#{current_story.id}" + " commit:" + "#{(Util::Shell.exec "git rev-parse HEAD").chomp[0..6]}"
|
140
|
-
params[:created_with] = "v2gpti"
|
141
|
-
params[:duration] = seconds_spent(time_spent)
|
142
|
-
params[:start] = (Time.now - params[:duration]).iso8601
|
143
|
-
task = @toggl.get_project_task_with_name(configuration.toggl_project_id, "#{current_story.id}")
|
144
|
-
if !task.nil?
|
145
|
-
params[:tid] = task['id']
|
146
|
-
end
|
147
|
-
params
|
148
|
-
rescue TogglException => te
|
149
|
-
$LOG.error("[TOGGL] ---------------- #{te.message}")
|
150
|
-
$LOG.error("[TOGGL] ---------------- #{te.message}")
|
151
|
-
params
|
152
|
-
end
|
153
|
-
|
91
|
+
|
154
92
|
def seconds_spent(time_spent)
|
155
93
|
seconds = 0
|
156
94
|
time_spent.scan(/(\d+)(\w)/).each do |amount, measure|
|
@@ -44,14 +44,6 @@ module GitPivotalTrackerIntegration
|
|
44
44
|
api_token
|
45
45
|
end
|
46
46
|
|
47
|
-
def toggl_project_id
|
48
|
-
toggle_config = self.pconfig["toggl"]
|
49
|
-
if toggle_config.nil?
|
50
|
-
abort "toggle project id not set"
|
51
|
-
else
|
52
|
-
toggle_config["project-id"]
|
53
|
-
end
|
54
|
-
end
|
55
47
|
|
56
48
|
def check_config_project_id
|
57
49
|
Util::Git.set_config("pivotal.project-id", self.pconfig["pivotal-tracker"]["project-id"])
|
@@ -43,16 +43,6 @@ module GitPivotalTrackerIntegration
|
|
43
43
|
|
44
44
|
self.commit_new_build
|
45
45
|
|
46
|
-
time_spent = ""
|
47
|
-
while 1
|
48
|
-
time_spent = ask("How much time did you spend on this task? (example: 15m, 2.5h)")
|
49
|
-
if (/\d/.match( time_spent )) && /[mhd]/.match(time_spent)
|
50
|
-
break
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
finish_toggle(@configuration, time_spent)
|
55
|
-
|
56
46
|
Util::Git.merge(@configuration.story(@project), no_complete)
|
57
47
|
Util::Git.push Util::Git.branch_name
|
58
48
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: v2gpti
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Wolski
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-
|
13
|
+
date: 2017-11-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: highline
|
@@ -186,28 +186,28 @@ dependencies:
|
|
186
186
|
requirements:
|
187
187
|
- - "~>"
|
188
188
|
- !ruby/object:Gem::Version
|
189
|
-
version: 4.2
|
189
|
+
version: '4.2'
|
190
190
|
type: :runtime
|
191
191
|
prerelease: false
|
192
192
|
version_requirements: !ruby/object:Gem::Requirement
|
193
193
|
requirements:
|
194
194
|
- - "~>"
|
195
195
|
- !ruby/object:Gem::Version
|
196
|
-
version: 4.2
|
196
|
+
version: '4.2'
|
197
197
|
- !ruby/object:Gem::Dependency
|
198
198
|
name: activemodel
|
199
199
|
requirement: !ruby/object:Gem::Requirement
|
200
200
|
requirements:
|
201
201
|
- - "~>"
|
202
202
|
- !ruby/object:Gem::Version
|
203
|
-
version: 4.2
|
203
|
+
version: '4.2'
|
204
204
|
type: :runtime
|
205
205
|
prerelease: false
|
206
206
|
version_requirements: !ruby/object:Gem::Requirement
|
207
207
|
requirements:
|
208
208
|
- - "~>"
|
209
209
|
- !ruby/object:Gem::Version
|
210
|
-
version: 4.2
|
210
|
+
version: '4.2'
|
211
211
|
- !ruby/object:Gem::Dependency
|
212
212
|
name: bundler
|
213
213
|
requirement: !ruby/object:Gem::Requirement
|
@@ -338,15 +338,15 @@ description: Provides a set of additional Git commands to help developers when w
|
|
338
338
|
with Pivotal Tracker
|
339
339
|
email: jeff@xxxxxxxxx.com
|
340
340
|
executables:
|
341
|
-
- git-deliver
|
342
|
-
- git-finish
|
343
|
-
- git-newbug
|
344
|
-
- git-newfeature
|
345
341
|
- git-qa
|
346
|
-
- git-
|
342
|
+
- git-uat
|
343
|
+
- git-newbug
|
344
|
+
- git-finish
|
347
345
|
- git-report
|
346
|
+
- git-newfeature
|
348
347
|
- git-start
|
349
|
-
- git-
|
348
|
+
- git-deliver
|
349
|
+
- git-release
|
350
350
|
extensions: []
|
351
351
|
extra_rdoc_files: []
|
352
352
|
files:
|
@@ -378,7 +378,6 @@ files:
|
|
378
378
|
- lib/git-pivotal-tracker-integration/util/git.rb
|
379
379
|
- lib/git-pivotal-tracker-integration/util/shell.rb
|
380
380
|
- lib/git-pivotal-tracker-integration/util/story.rb
|
381
|
-
- lib/git-pivotal-tracker-integration/util/togglV8.rb
|
382
381
|
- lib/git-pivotal-tracker-integration/version-update/gradle.rb
|
383
382
|
- spec/git-pivotal-tracker-integration/command/base_spec.rb
|
384
383
|
- spec/git-pivotal-tracker-integration/command/configuration_spec.rb
|
@@ -447,17 +446,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
447
446
|
version: '0'
|
448
447
|
requirements: []
|
449
448
|
rubyforge_project:
|
450
|
-
rubygems_version: 2.5.1
|
449
|
+
rubygems_version: 2.5.2.1
|
451
450
|
signing_key:
|
452
451
|
specification_version: 4
|
453
452
|
summary: Git commands for integration with Pivotal Tracker
|
454
453
|
test_files:
|
455
|
-
- spec/git-pivotal-tracker-integration/command/base_spec.rb
|
456
|
-
- spec/git-pivotal-tracker-integration/command/configuration_spec.rb
|
457
|
-
- spec/git-pivotal-tracker-integration/command/finish_spec.rb
|
458
|
-
- spec/git-pivotal-tracker-integration/command/release_spec.rb
|
459
|
-
- spec/git-pivotal-tracker-integration/command/start_spec.rb
|
460
454
|
- spec/git-pivotal-tracker-integration/util/git_spec.rb
|
461
455
|
- spec/git-pivotal-tracker-integration/util/shell_spec.rb
|
462
456
|
- spec/git-pivotal-tracker-integration/util/story_spec.rb
|
463
457
|
- spec/git-pivotal-tracker-integration/version-update/gradle_spec.rb
|
458
|
+
- spec/git-pivotal-tracker-integration/command/configuration_spec.rb
|
459
|
+
- spec/git-pivotal-tracker-integration/command/finish_spec.rb
|
460
|
+
- spec/git-pivotal-tracker-integration/command/start_spec.rb
|
461
|
+
- spec/git-pivotal-tracker-integration/command/release_spec.rb
|
462
|
+
- spec/git-pivotal-tracker-integration/command/base_spec.rb
|
@@ -1,438 +0,0 @@
|
|
1
|
-
#! /usr/bin/env rvm ruby-1.9.3-head do ruby
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'logger'
|
6
|
-
require 'faraday'
|
7
|
-
require 'json'
|
8
|
-
|
9
|
-
require 'awesome_print' # for debug output
|
10
|
-
|
11
|
-
class TogglException < StandardError
|
12
|
-
def initialize(message)
|
13
|
-
@message = "[Toggl] #{message}"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Toggl
|
18
|
-
attr_accessor :conn, :debug
|
19
|
-
|
20
|
-
def initialize(username=nil, password='api_token', debug=nil)
|
21
|
-
self.debug_on(debug) if !debug.nil?
|
22
|
-
if (password.to_s == 'api_token' && username.to_s == '')
|
23
|
-
toggl_api_file = self.toggl_file
|
24
|
-
username = IO.read(toggl_api_file).strip
|
25
|
-
end
|
26
|
-
|
27
|
-
@conn = connection(username, password)
|
28
|
-
end
|
29
|
-
|
30
|
-
def toggl_file
|
31
|
-
t_file = ENV['HOME']+'/.toggl'
|
32
|
-
if !FileTest.exist?(t_file) then
|
33
|
-
puts "\n\nIt looks like this is the first time you have used Toggl on this machine.\n"
|
34
|
-
t_API_key = ask("Please enter your Toggl API key:")
|
35
|
-
output = File.open( t_file, "w")
|
36
|
-
output << t_API_key
|
37
|
-
output.close
|
38
|
-
end
|
39
|
-
|
40
|
-
t_file
|
41
|
-
end
|
42
|
-
def connection(username, password)
|
43
|
-
Faraday.new(url: 'https://www.toggl.com/api/v8', :ssl => {:verify => false}) do |faraday|
|
44
|
-
faraday.request :url_encoded
|
45
|
-
faraday.response :logger, Logger.new('faraday.log')
|
46
|
-
faraday.adapter Faraday.default_adapter
|
47
|
-
faraday.headers = {"Content-Type" => "application/json"}
|
48
|
-
faraday.basic_auth username, password
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def debug_on(debug=true)
|
53
|
-
puts "debugging is %s" % [debug ? "ON" : "OFF"]
|
54
|
-
@debug = debug
|
55
|
-
end
|
56
|
-
|
57
|
-
def checkParams(params, fields=[])
|
58
|
-
raise ArgumentError, 'params is not a Hash' unless params.is_a? Hash
|
59
|
-
return if fields.empty?
|
60
|
-
errors = []
|
61
|
-
for f in fields
|
62
|
-
errors.push("params[#{f}] is required") unless params.has_key?(f)
|
63
|
-
end
|
64
|
-
raise ArgumentError, errors.join(', ') if !errors.empty?
|
65
|
-
end
|
66
|
-
|
67
|
-
#----------#
|
68
|
-
#--- Me ---#
|
69
|
-
#----------#
|
70
|
-
|
71
|
-
def me(all=nil)
|
72
|
-
# TODO: Reconcile this with get_client_projects
|
73
|
-
get "me%s" % [all.nil? ? "" : "?with_related_data=#{all}"]
|
74
|
-
rescue TogglException => te
|
75
|
-
puts "Failed to retrieve the Toggl User Id"
|
76
|
-
raise te
|
77
|
-
end
|
78
|
-
|
79
|
-
def my_clients(user)
|
80
|
-
user['projects']
|
81
|
-
end
|
82
|
-
|
83
|
-
def my_projects(user)
|
84
|
-
user['projects']
|
85
|
-
end
|
86
|
-
|
87
|
-
def my_tags(user)
|
88
|
-
user['tags']
|
89
|
-
end
|
90
|
-
|
91
|
-
def my_time_entries(user)
|
92
|
-
user['time_entries']
|
93
|
-
end
|
94
|
-
|
95
|
-
def my_workspaces(user)
|
96
|
-
user['workspaces']
|
97
|
-
end
|
98
|
-
|
99
|
-
#---------------#
|
100
|
-
#--- Clients ---#
|
101
|
-
#---------------#
|
102
|
-
|
103
|
-
# name : The name of the client (string, required, unique in workspace)
|
104
|
-
# wid : workspace ID, where the client will be used (integer, required)
|
105
|
-
# notes : Notes for the client (string, not required)
|
106
|
-
# hrate : The hourly rate for this client (float, not required, available only for pro workspaces)
|
107
|
-
# cur : The name of the client's currency (string, not required, available only for pro workspaces)
|
108
|
-
# at : timestamp that is sent in the response, indicates the time client was last updated
|
109
|
-
|
110
|
-
def create_client(params)
|
111
|
-
checkParams(params, [:name, :wid])
|
112
|
-
post "clients", {client: params}
|
113
|
-
end
|
114
|
-
|
115
|
-
def get_client(client_id)
|
116
|
-
get "clients/#{client_id}"
|
117
|
-
end
|
118
|
-
|
119
|
-
def update_client(client_id, params)
|
120
|
-
put "clients/#{client_id}", {client: params}
|
121
|
-
end
|
122
|
-
|
123
|
-
def delete_client(client_id)
|
124
|
-
delete "clients/#{client_id}"
|
125
|
-
end
|
126
|
-
|
127
|
-
def get_client_projects(client_id, params={})
|
128
|
-
active = params.has_key?(:active) ? "?active=#{params[:active]}" : ""
|
129
|
-
get "clients/#{client_id}/projects#{active}"
|
130
|
-
end
|
131
|
-
|
132
|
-
|
133
|
-
#----------------#
|
134
|
-
#--- Projects ---#
|
135
|
-
#----------------#
|
136
|
-
|
137
|
-
# name : The name of the project (string, required, unique for client and workspace)
|
138
|
-
# wid : workspace ID, where the project will be saved (integer, required)
|
139
|
-
# cid : client ID(integer, not required)
|
140
|
-
# active : whether the project is archived or not (boolean, by default true)
|
141
|
-
# is_private : whether project is accessible for only project users or for all workspace users (boolean, default true)
|
142
|
-
# template : whether the project can be used as a template (boolean, not required)
|
143
|
-
# template_id : id of the template project used on current project's creation
|
144
|
-
# billable : whether the project is billable or not (boolean, default true, available only for pro workspaces)
|
145
|
-
# at : timestamp that is sent in the response for PUT, indicates the time task was last updated
|
146
|
-
# -- Undocumented --
|
147
|
-
# color : number (in the range 0-23?)
|
148
|
-
|
149
|
-
def create_project(params)
|
150
|
-
checkParams(params, [:name, :wid])
|
151
|
-
post "projects", {project: params}
|
152
|
-
end
|
153
|
-
|
154
|
-
def get_project(project_id)
|
155
|
-
get "projects/#{project_id}"
|
156
|
-
end
|
157
|
-
|
158
|
-
def update_project(project_id, params)
|
159
|
-
put "projects/#{project_id}", {project: params}
|
160
|
-
end
|
161
|
-
|
162
|
-
def get_project_users(project_id)
|
163
|
-
get "projects/#{project_id}/project_users"
|
164
|
-
end
|
165
|
-
|
166
|
-
def get_project_tasks(project_id)
|
167
|
-
get "projects/#{project_id}/tasks"
|
168
|
-
end
|
169
|
-
|
170
|
-
def get_project_task_with_name(project_id, task_name)
|
171
|
-
task = nil
|
172
|
-
project_tasks = get_project_tasks(project_id) || []
|
173
|
-
project_tasks.each { |a_task|
|
174
|
-
a_task_name = "#{a_task["name"]}"
|
175
|
-
if (a_task_name.include?task_name)
|
176
|
-
task = a_task
|
177
|
-
break
|
178
|
-
end
|
179
|
-
}
|
180
|
-
task
|
181
|
-
end
|
182
|
-
#---------------------#
|
183
|
-
#--- Project users ---#
|
184
|
-
#---------------------#
|
185
|
-
|
186
|
-
# pid : project ID (integer, required)
|
187
|
-
# uid : user ID, who is added to the project (integer, required)
|
188
|
-
# wid : workspace ID, where the project belongs to (integer, not-required, project's workspace id is used)
|
189
|
-
# manager : admin rights for this project (boolean, default false)
|
190
|
-
# rate : hourly rate for the project user (float, not-required, only for pro workspaces) in the currency of the project's client or in workspace default currency.
|
191
|
-
# at : timestamp that is sent in the response, indicates when the project user was last updated
|
192
|
-
# -- Additional fields --
|
193
|
-
# fullname : full name of the user, who is added to the project
|
194
|
-
|
195
|
-
def create_project_user(params)
|
196
|
-
checkParams(params, [:pid, :uid])
|
197
|
-
params[:fields] = "fullname" # for simplicity, always request fullname field
|
198
|
-
post "project_users", {project_user: params}
|
199
|
-
end
|
200
|
-
|
201
|
-
def update_project_user(project_user_id, params)
|
202
|
-
params[:fields] = "fullname" # for simplicity, always request fullname field
|
203
|
-
put "project_users/#{project_user_id}", {project_user: params}
|
204
|
-
end
|
205
|
-
|
206
|
-
def delete_project_user(project_user_id)
|
207
|
-
delete "project_users/#{project_user_id}"
|
208
|
-
end
|
209
|
-
|
210
|
-
#------------#
|
211
|
-
#--- Tags ---#
|
212
|
-
#------------#
|
213
|
-
|
214
|
-
# name : The name of the tag (string, required, unique in workspace)
|
215
|
-
# wid : workspace ID, where the tag will be used (integer, required)
|
216
|
-
|
217
|
-
def create_tag(params)
|
218
|
-
checkParams(params, [:name, :wid])
|
219
|
-
post "tags", {tag: params}
|
220
|
-
end
|
221
|
-
|
222
|
-
# ex: update_tag(12345, {name: "same tame game"})
|
223
|
-
def update_tag(tag_id, params)
|
224
|
-
put "tags/#{tag_id}", {tag: params}
|
225
|
-
end
|
226
|
-
|
227
|
-
def delete_tag(tag_id)
|
228
|
-
delete "tags/#{tag_id}"
|
229
|
-
end
|
230
|
-
|
231
|
-
#-------------#
|
232
|
-
#--- Tasks ---#
|
233
|
-
#-------------#
|
234
|
-
|
235
|
-
# name : The name of the task (string, required, unique in project)
|
236
|
-
# pid : project ID for the task (integer, required)
|
237
|
-
# wid : workspace ID, where the task will be saved (integer, project's workspace id is used when not supplied)
|
238
|
-
# uid : user ID, to whom the task is assigned to (integer, not required)
|
239
|
-
# estimated_seconds : estimated duration of task in seconds (integer, not required)
|
240
|
-
# active : whether the task is done or not (boolean, by default true)
|
241
|
-
# at : timestamp that is sent in the response for PUT, indicates the time task was last updated
|
242
|
-
# -- Additional fields --
|
243
|
-
# done_seconds : duration (in seconds) of all the time entries registered for this task
|
244
|
-
# uname : full name of the person to whom the task is assigned to
|
245
|
-
|
246
|
-
def create_task(params)
|
247
|
-
checkParams(params, [:name, :pid])
|
248
|
-
post "tasks", {task: params}
|
249
|
-
end
|
250
|
-
|
251
|
-
def get_task(task_id)
|
252
|
-
get "tasks/#{task_id}"
|
253
|
-
end
|
254
|
-
|
255
|
-
# ex: update_task(1894675, {active: true, estimated_seconds: 4500, fields: "done_seconds,uname"})
|
256
|
-
def update_task(*task_id, params)
|
257
|
-
put "tasks/#{task_id.join(',')}", {task: params}
|
258
|
-
end
|
259
|
-
|
260
|
-
def delete_task(*task_id)
|
261
|
-
delete "tasks/#{task_id.join(',')}"
|
262
|
-
end
|
263
|
-
|
264
|
-
#--------------------#
|
265
|
-
#--- Time entries ---#
|
266
|
-
#--------------------#
|
267
|
-
|
268
|
-
# description : (string, required)
|
269
|
-
# wid : workspace ID (integer, required if pid or tid not supplied)
|
270
|
-
# pid : project ID (integer, not required)
|
271
|
-
# tid : task ID (integer, not required)
|
272
|
-
# billable : (boolean, not required, default false, available for pro workspaces)
|
273
|
-
# start : time entry start time (string, required, ISO 8601 date and time)
|
274
|
-
# stop : time entry stop time (string, not required, ISO 8601 date and time)
|
275
|
-
# duration : time entry duration in seconds. If the time entry is currently running, the duration attribute contains a negative value, denoting the start of the time entry in seconds since epoch (Jan 1 1970). The correct duration can be calculated as current_time + duration, where current_time is the current time in seconds since epoch. (integer, required)
|
276
|
-
# created_with : the name of your client app (string, required)
|
277
|
-
# tags : a list of tag names (array of strings, not required)
|
278
|
-
# duronly : should Toggl show the start and stop time of this time entry? (boolean, not required)
|
279
|
-
# at : timestamp that is sent in the response, indicates the time item was last updated
|
280
|
-
|
281
|
-
def create_time_entry(params)
|
282
|
-
checkParams(params, [:description, :start, :created_with])
|
283
|
-
if !params.has_key?(:wid) and !params.has_key?(:pid) and !params.has_key?(:tid) then
|
284
|
-
raise ArgumentError, "one of params['wid'], params['pid'], params['tid'] is required"
|
285
|
-
end
|
286
|
-
post "time_entries", {time_entry: params}
|
287
|
-
end
|
288
|
-
|
289
|
-
def start_time_entry(params)
|
290
|
-
if !params.has_key?(:wid) and !params.has_key?(:pid) and !params.has_key?(:tid) then
|
291
|
-
raise ArgumentError, "one of params['wid'], params['pid'], params['tid'] is required"
|
292
|
-
end
|
293
|
-
post "time_entries/start", {time_entry: params}
|
294
|
-
end
|
295
|
-
|
296
|
-
def stop_time_entry(time_entry_id)
|
297
|
-
put "time_entries/#{time_entry_id}/stop", {}
|
298
|
-
end
|
299
|
-
|
300
|
-
def get_time_entry(time_entry_id)
|
301
|
-
get "time_entries/#{time_entry_id}"
|
302
|
-
end
|
303
|
-
|
304
|
-
def update_time_entry(time_entry_id, params)
|
305
|
-
put "time_entries/#{time_entry_id}", {time_entry: params}
|
306
|
-
end
|
307
|
-
|
308
|
-
def delete_time_entry(time_entry_id)
|
309
|
-
delete "time_entries/#{time_entry_id}"
|
310
|
-
end
|
311
|
-
|
312
|
-
def iso8601(date)
|
313
|
-
return nil if date.nil?
|
314
|
-
if date.is_a?(Time) or date.is_a?(Date)
|
315
|
-
iso = date.iso8601
|
316
|
-
elsif date.is_a?(String)
|
317
|
-
iso = DateTime.parse(date).iso8601
|
318
|
-
else
|
319
|
-
raise ArgumentError, "Can't convert #{date.class} to ISO-8601 Date/Time"
|
320
|
-
end
|
321
|
-
return Faraday::Utils.escape(iso)
|
322
|
-
end
|
323
|
-
|
324
|
-
def get_time_entries(start_date=nil, end_date=nil)
|
325
|
-
params = []
|
326
|
-
params.push("start_date=#{iso8601(start_date)}") if !start_date.nil?
|
327
|
-
params.push("end_date=#{iso8601(end_date)}") if !end_date.nil?
|
328
|
-
get "time_entries%s" % [params.empty? ? "" : "?#{params.join('&')}"]
|
329
|
-
end
|
330
|
-
|
331
|
-
#-------------#
|
332
|
-
#--- Users ---#
|
333
|
-
#-------------#
|
334
|
-
|
335
|
-
# api_token : (string)
|
336
|
-
# default_wid : default workspace id (integer)
|
337
|
-
# email : (string)
|
338
|
-
# jquery_timeofday_format : (string)
|
339
|
-
# jquery_date_format :(string)
|
340
|
-
# timeofday_format : (string)
|
341
|
-
# date_format : (string)
|
342
|
-
# store_start_and_stop_time : whether start and stop time are saved on time entry (boolean)
|
343
|
-
# beginning_of_week : (integer, Sunday=0)
|
344
|
-
# language : user's language (string)
|
345
|
-
# image_url : url with the user's profile picture(string)
|
346
|
-
# sidebar_piechart : should a piechart be shown on the sidebar (boolean)
|
347
|
-
# at : timestamp of last changes
|
348
|
-
# new_blog_post : an object with toggl blog post title and link
|
349
|
-
|
350
|
-
#------------------#
|
351
|
-
#--- Workspaces ---#
|
352
|
-
#------------------#
|
353
|
-
|
354
|
-
# name : (string, required)
|
355
|
-
# premium : If it's a pro workspace or not. Shows if someone is paying for the workspace or not (boolean, not required)
|
356
|
-
# at : timestamp that is sent in the response, indicates the time item was last updated
|
357
|
-
|
358
|
-
def workspaces
|
359
|
-
get "workspaces"
|
360
|
-
end
|
361
|
-
|
362
|
-
def clients(workspace=nil)
|
363
|
-
if workspace.nil?
|
364
|
-
get "clients"
|
365
|
-
else
|
366
|
-
get "workspaces/#{workspace}/clients"
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
def projects(workspace, params={})
|
371
|
-
active = params.has_key?(:active) ? "?active=#{params[:active]}" : ""
|
372
|
-
get "workspaces/#{workspace}/projects#{active}"
|
373
|
-
end
|
374
|
-
|
375
|
-
def users(workspace)
|
376
|
-
get "workspaces/#{workspace}/users"
|
377
|
-
end
|
378
|
-
|
379
|
-
def tasks(workspace, params={})
|
380
|
-
active = params.has_key?(:active) ? "?active=#{params[:active]}" : ""
|
381
|
-
get "workspaces/#{workspace}/tasks#{active}"
|
382
|
-
end
|
383
|
-
|
384
|
-
#---------------#
|
385
|
-
#--- Private ---#
|
386
|
-
#---------------#
|
387
|
-
|
388
|
-
private
|
389
|
-
|
390
|
-
def get(resource)
|
391
|
-
puts "GET #{resource}" if @debug
|
392
|
-
full_res = self.conn.get(resource)
|
393
|
-
# ap full_res.env if @debug
|
394
|
-
return nil if full_res.env[:body] == 'null'
|
395
|
-
res = JSON.parse(full_res.env[:body])
|
396
|
-
res.is_a?(Array) || res['data'].nil? ? res : res['data']
|
397
|
-
rescue StandardError => e
|
398
|
-
raise TogglException, "GET #{resource} Failed -- #{e.message}"
|
399
|
-
end
|
400
|
-
|
401
|
-
def post(resource, data)
|
402
|
-
puts "POST #{resource} / #{data}" if @debug
|
403
|
-
full_res = self.conn.post(resource, JSON.generate(data))
|
404
|
-
#ap full_res.env if @debug
|
405
|
-
if (200 == full_res.env[:status]) then
|
406
|
-
res = JSON.parse(full_res.env[:body])
|
407
|
-
res['data'].nil? ? res : res['data']
|
408
|
-
else
|
409
|
-
puts(full_res.env[:body])
|
410
|
-
end
|
411
|
-
rescue StandardError => e
|
412
|
-
raise TogglException, "POST #{resource} / #{data} Failed -- #{e.message}"
|
413
|
-
end
|
414
|
-
|
415
|
-
def put(resource, data)
|
416
|
-
puts "PUT #{resource} / #{data}" if @debug
|
417
|
-
full_res = self.conn.put(resource, JSON.generate(data))
|
418
|
-
# ap full_res.env if @debug
|
419
|
-
if (200 == full_res.env[:status]) then
|
420
|
-
res = JSON.parse(full_res.env[:body])
|
421
|
-
res['data'].nil? ? res : res['data']
|
422
|
-
else
|
423
|
-
puts(full_res.env[:body])
|
424
|
-
end
|
425
|
-
rescue StandardError => e
|
426
|
-
raise TogglException, "PUT #{resource} / #{data} Failed -- #{e.message}"
|
427
|
-
end
|
428
|
-
|
429
|
-
def delete(resource)
|
430
|
-
puts "DELETE #{resource}" if @debug
|
431
|
-
full_res = self.conn.delete(resource)
|
432
|
-
# ap full_res.env if @debug
|
433
|
-
(200 == full_res.env[:status]) ? "" : puts(full_res.env[:body])
|
434
|
-
rescue StandardError => e
|
435
|
-
raise TogglException, "DELETE #{resource} Failed -- #{e.message}"
|
436
|
-
end
|
437
|
-
|
438
|
-
end
|