teamwork_api 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +11 -1
- data/.travis.yml +14 -1
- data/CHANGELOG.md +14 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +65 -10
- data/Guardfile +12 -0
- data/README.md +5 -5
- data/Rakefile +2 -0
- data/lib/teamwork_api.rb +3 -0
- data/lib/teamwork_api/api/companies.rb +4 -0
- data/lib/teamwork_api/api/params.rb +18 -11
- data/lib/teamwork_api/api/people.rb +52 -29
- data/lib/teamwork_api/api/project_owner.rb +6 -1
- data/lib/teamwork_api/api/projects.rb +70 -47
- data/lib/teamwork_api/api/task_lists.rb +8 -4
- data/lib/teamwork_api/client.rb +24 -20
- data/lib/teamwork_api/error.rb +7 -1
- data/lib/teamwork_api/version.rb +3 -1
- data/spec/fixtures/companies.json +64 -0
- data/spec/fixtures/company.json +32 -0
- data/spec/fixtures/create_project.json +4 -0
- data/spec/fixtures/create_task_list.json +4 -0
- data/spec/fixtures/delete.json +3 -0
- data/spec/fixtures/people.json +80 -0
- data/spec/fixtures/person.json +77 -0
- data/spec/fixtures/project.json +68 -0
- data/spec/fixtures/project_owner.json +91 -0
- data/spec/fixtures/projects.json +135 -0
- data/spec/fixtures/task_list.json +18 -0
- data/spec/fixtures/task_lists.json +22 -0
- data/spec/fixtures/update.json +3 -0
- data/spec/spec_helper.rb +60 -7
- data/spec/teamwork_api/api/companies_spec.rb +69 -0
- data/spec/teamwork_api/api/people_spec.rb +78 -0
- data/spec/teamwork_api/api/project_owner_spec.rb +35 -0
- data/spec/teamwork_api/api/projects_spec.rb +117 -0
- data/spec/teamwork_api/api/task_lists_spec.rb +98 -0
- data/spec/teamwork_api/client_spec.rb +202 -0
- data/teamwork_api.gemspec +10 -2
- metadata +116 -8
- data/spec/teamwork_api_spec.rb +0 -9
@@ -1,71 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TeamworkApi
|
2
4
|
module API
|
5
|
+
# Client methods for Projects
|
6
|
+
# https://developer.teamwork.com/projects/projects
|
3
7
|
module Projects
|
8
|
+
OPTIONAL_GET_ATTRIBUTES = [
|
9
|
+
:status,
|
10
|
+
:updated_after_date,
|
11
|
+
:order_by,
|
12
|
+
:created_after_date,
|
13
|
+
:created_after_time,
|
14
|
+
:cat_id,
|
15
|
+
:include_people,
|
16
|
+
:include_project_owner,
|
17
|
+
:page,
|
18
|
+
:page_size,
|
19
|
+
:order_mode,
|
20
|
+
:only_starred_projects,
|
21
|
+
:company_id,
|
22
|
+
:project_owner_ids,
|
23
|
+
:search_term,
|
24
|
+
:get_deleted,
|
25
|
+
:include_tags,
|
26
|
+
:user_id,
|
27
|
+
:updated_after_date_time
|
28
|
+
].freeze
|
29
|
+
OPTIONAL_CREATE_ATTRIBUTES = [
|
30
|
+
:description,
|
31
|
+
:start_date,
|
32
|
+
:end_date,
|
33
|
+
:company_id,
|
34
|
+
:new_company,
|
35
|
+
:'harvest-timers-enabled',
|
36
|
+
:tags,
|
37
|
+
:reply_by_email_enabled,
|
38
|
+
:privacy_enabled
|
39
|
+
].freeze
|
40
|
+
OPTIONAL_UPDATE_ATTRIBUTES = [
|
41
|
+
:name,
|
42
|
+
:description,
|
43
|
+
:start_date,
|
44
|
+
:end_date,
|
45
|
+
:company_id,
|
46
|
+
:new_company,
|
47
|
+
:status,
|
48
|
+
:'category-id',
|
49
|
+
:'harvest-timers-enabled',
|
50
|
+
:tags,
|
51
|
+
:reply_by_email_enabled,
|
52
|
+
:privacy_enabled,
|
53
|
+
:'use-tasks',
|
54
|
+
:'use-messages',
|
55
|
+
:'use-time',
|
56
|
+
:'use-risk-register',
|
57
|
+
:'use-billing',
|
58
|
+
:'use-milestones',
|
59
|
+
:'use-files',
|
60
|
+
:'use-notebook',
|
61
|
+
:'use-links',
|
62
|
+
:default_privacy
|
63
|
+
].freeze
|
64
|
+
|
4
65
|
def create_project(args)
|
5
66
|
args =
|
6
67
|
API.params(args)
|
7
68
|
.required(:name)
|
8
69
|
.default('category-id': '0')
|
9
|
-
.optional(
|
10
|
-
|
11
|
-
:start_date,
|
12
|
-
:end_date,
|
13
|
-
:company_id,
|
14
|
-
:new_company,
|
15
|
-
:'harvest-timers-enabled',
|
16
|
-
:tags,
|
17
|
-
:reply_by_email_enabled,
|
18
|
-
:privacy_enabled
|
19
|
-
).to_h
|
70
|
+
.optional(*OPTIONAL_CREATE_ATTRIBUTES)
|
71
|
+
.to_h
|
20
72
|
|
21
73
|
response = post 'projects.json', project: args
|
22
|
-
response['id']
|
74
|
+
response['id']&.to_i
|
23
75
|
end
|
24
76
|
|
25
77
|
def update_project(project_id, args)
|
26
|
-
args =
|
27
|
-
API.params(args)
|
28
|
-
.optional(
|
29
|
-
:name,
|
30
|
-
:description,
|
31
|
-
:start_date,
|
32
|
-
:end_date,
|
33
|
-
:company_id,
|
34
|
-
:new_company,
|
35
|
-
:status,
|
36
|
-
:'category-id',
|
37
|
-
:'harvest-timers-enabled',
|
38
|
-
:tags,
|
39
|
-
:reply_by_email_enabled,
|
40
|
-
:privacy_enabled,
|
41
|
-
:'use-tasks',
|
42
|
-
:'use-messages',
|
43
|
-
:'use-time',
|
44
|
-
:'use-risk-register',
|
45
|
-
:'use-billing',
|
46
|
-
:'use-milestones',
|
47
|
-
:'use-files',
|
48
|
-
:'use-notebook',
|
49
|
-
:'use-links',
|
50
|
-
:default_privacy
|
51
|
-
).to_h
|
78
|
+
args = API.params(args).optional(*OPTIONAL_UPDATE_ATTRIBUTES).to_h
|
52
79
|
|
53
|
-
|
54
|
-
response['id']
|
80
|
+
put "projects/#{project_id}.json", project: args
|
55
81
|
end
|
56
82
|
|
57
83
|
def project(project_id, args = {})
|
58
|
-
|
59
|
-
args = { project: args }
|
60
|
-
else
|
61
|
-
args = {}
|
62
|
-
end
|
84
|
+
args = { project: args } unless args.empty?
|
63
85
|
response = get "/projects/#{project_id}.json", args
|
64
86
|
response.body['project']
|
65
87
|
end
|
66
88
|
|
67
|
-
def projects
|
68
|
-
|
89
|
+
def projects(args = {})
|
90
|
+
args = API.params(args).optional(*OPTIONAL_GET_ATTRIBUTES).to_h
|
91
|
+
response = get '/projects.json', args
|
69
92
|
response.body['projects']
|
70
93
|
end
|
71
94
|
|
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TeamworkApi
|
2
4
|
module API
|
5
|
+
# Client methods for TaskLists
|
6
|
+
# https://developer.teamwork.com/projects/task-lists
|
3
7
|
module TaskLists
|
4
8
|
def create_task_list(project_id, args)
|
5
9
|
args =
|
@@ -17,15 +21,15 @@ module TeamworkApi
|
|
17
21
|
).to_h
|
18
22
|
|
19
23
|
response = post "projects/#{project_id}/tasklists.json", tasklist: args
|
20
|
-
response['TASKLISTID']
|
24
|
+
response['TASKLISTID']&.to_i
|
21
25
|
end
|
22
26
|
|
23
|
-
def update_task_list(task_list_id, args)
|
24
|
-
end
|
27
|
+
# def update_task_list(task_list_id, args)
|
28
|
+
# end
|
25
29
|
|
26
30
|
def task_list(task_list_id)
|
27
31
|
response = get "/tasklists/#{task_list_id}.json"
|
28
|
-
response.body['
|
32
|
+
response.body['todo-list']
|
29
33
|
end
|
30
34
|
|
31
35
|
def task_lists
|
data/lib/teamwork_api/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'faraday_middleware'
|
3
5
|
require 'json'
|
@@ -10,6 +12,7 @@ require 'teamwork_api/api/project_owner'
|
|
10
12
|
require 'teamwork_api/api/task_lists'
|
11
13
|
|
12
14
|
module TeamworkApi
|
15
|
+
# The main Teamwork client object
|
13
16
|
class Client
|
14
17
|
attr_accessor :api_key
|
15
18
|
attr_reader :host
|
@@ -91,14 +94,10 @@ module TeamworkApi
|
|
91
94
|
end
|
92
95
|
|
93
96
|
def request(method, path, params = {})
|
94
|
-
unless Hash === params
|
95
|
-
params = params.to_h if params.respond_to? :to_h
|
96
|
-
end
|
97
|
-
path = @use_relative ? path.sub(/^\//, '') : path
|
98
|
-
|
99
97
|
connection.headers[:cache_control] = 'no-cache'
|
100
98
|
connection.basic_auth(api_key, '')
|
101
|
-
response =
|
99
|
+
response =
|
100
|
+
connection.send(method.to_sym, request_path(path), params_hash(params))
|
102
101
|
handle_error(response)
|
103
102
|
response.env
|
104
103
|
rescue Faraday::Error::ClientError, JSON::ParserError
|
@@ -106,31 +105,36 @@ module TeamworkApi
|
|
106
105
|
end
|
107
106
|
|
108
107
|
def handle_error(response)
|
108
|
+
body = response.env[:body]
|
109
|
+
env = response.env
|
110
|
+
|
109
111
|
case response.status
|
110
112
|
when 403
|
111
|
-
raise TeamworkApi::UnauthenticatedError.new(
|
112
|
-
response.env[:body],
|
113
|
-
response.env
|
114
|
-
)
|
113
|
+
raise TeamworkApi::UnauthenticatedError.new(body, env)
|
115
114
|
when 404, 410
|
116
|
-
raise TeamworkApi::NotFoundError.new(
|
115
|
+
raise TeamworkApi::NotFoundError.new(body, env)
|
117
116
|
when 422
|
118
|
-
raise TeamworkApi::UnprocessableEntity.new(
|
119
|
-
response.env[:body],
|
120
|
-
response.env
|
121
|
-
)
|
117
|
+
raise TeamworkApi::UnprocessableEntity.new(body, env)
|
122
118
|
when 429
|
123
|
-
raise TeamworkApi::TooManyRequests.new(
|
124
|
-
response.env[:body],
|
125
|
-
response.env
|
126
|
-
)
|
119
|
+
raise TeamworkApi::TooManyRequests.new(body, env)
|
127
120
|
when 500...600
|
128
|
-
raise TeamworkApi::Error
|
121
|
+
raise TeamworkApi::Error, body
|
129
122
|
end
|
130
123
|
end
|
131
124
|
|
132
125
|
def check_subdirectory(host)
|
133
126
|
URI(host).request_uri != '/'
|
134
127
|
end
|
128
|
+
|
129
|
+
def request_path(path)
|
130
|
+
@use_relative ? path.sub(%r{^\/}, '') : path
|
131
|
+
end
|
132
|
+
|
133
|
+
def params_hash(params)
|
134
|
+
unless params.is_a?(Hash)
|
135
|
+
params = params.to_h if params.respond_to? :to_h
|
136
|
+
end
|
137
|
+
params
|
138
|
+
end
|
135
139
|
end
|
136
140
|
end
|
data/lib/teamwork_api/error.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
|
1
5
|
module TeamworkApi
|
6
|
+
# baser error
|
2
7
|
class TeamworkError < StandardError
|
3
8
|
attr_reader :response
|
4
9
|
|
@@ -8,6 +13,7 @@ module TeamworkApi
|
|
8
13
|
end
|
9
14
|
end
|
10
15
|
|
16
|
+
# specific errors
|
11
17
|
class Error < TeamworkError
|
12
18
|
attr_reader :wrapped_exception
|
13
19
|
|
@@ -15,7 +21,7 @@ module TeamworkApi
|
|
15
21
|
#
|
16
22
|
# @param exception [Exception, String]
|
17
23
|
# @return [TeamworkApi::Error]
|
18
|
-
def initialize(exception =
|
24
|
+
def initialize(exception = $ERROR_INFO)
|
19
25
|
@wrapped_exception = exception
|
20
26
|
if exception.respond_to?(:message)
|
21
27
|
super(exception.message)
|
data/lib/teamwork_api/version.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
{
|
2
|
+
"companies": [
|
3
|
+
{
|
4
|
+
"state": "California",
|
5
|
+
"email_one": "",
|
6
|
+
"email_three": "",
|
7
|
+
"contacts": "0",
|
8
|
+
"website": "https://www.company-one.com/",
|
9
|
+
"logo-URL": "https://s3.amazonaws.com/TWFiles/000/companyLogo/l.png",
|
10
|
+
"email_two": "",
|
11
|
+
"cid": "",
|
12
|
+
"phone": "",
|
13
|
+
"created-on": "",
|
14
|
+
"accounts": "15",
|
15
|
+
"company_name_url": "000-company-one",
|
16
|
+
"can_see_private": true,
|
17
|
+
"tags": [],
|
18
|
+
"zip": "90021",
|
19
|
+
"industryId": "",
|
20
|
+
"id": "000",
|
21
|
+
"last-changed-on": "2018-12-11T20:18:08Z",
|
22
|
+
"fax": "",
|
23
|
+
"address_two": "",
|
24
|
+
"name": "Company One",
|
25
|
+
"country": "United States",
|
26
|
+
"isowner": "1",
|
27
|
+
"industry": "",
|
28
|
+
"address_one": "1 First Avenue",
|
29
|
+
"countrycode": "US",
|
30
|
+
"collaborators": "2",
|
31
|
+
"city": "Los Angeles"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"state": "",
|
35
|
+
"email_one": "",
|
36
|
+
"email_three": "",
|
37
|
+
"contacts": "0",
|
38
|
+
"website": "",
|
39
|
+
"logo-URL": "",
|
40
|
+
"email_two": "",
|
41
|
+
"cid": "",
|
42
|
+
"phone": "",
|
43
|
+
"created-on": "2019-03-14T22:51:24Z",
|
44
|
+
"accounts": "0",
|
45
|
+
"company_name_url": "001-company-two",
|
46
|
+
"can_see_private": false,
|
47
|
+
"tags": [],
|
48
|
+
"zip": "",
|
49
|
+
"industryId": "",
|
50
|
+
"id": "001",
|
51
|
+
"last-changed-on": "2019-03-14T22:51:24Z",
|
52
|
+
"fax": "",
|
53
|
+
"address_two": "",
|
54
|
+
"name": "Company Two",
|
55
|
+
"country": "",
|
56
|
+
"isowner": "0",
|
57
|
+
"industry": "",
|
58
|
+
"address_one": "",
|
59
|
+
"countrycode": "",
|
60
|
+
"collaborators": "0",
|
61
|
+
"city": ""
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"company": {
|
3
|
+
"state": "California",
|
4
|
+
"email_one": "",
|
5
|
+
"email_three": "",
|
6
|
+
"contacts": "0",
|
7
|
+
"website": "https://www.company-one.com/",
|
8
|
+
"logo-URL": "https://s3.amazonaws.com/TWFiles/999/companyLogo/l.png",
|
9
|
+
"email_two": "",
|
10
|
+
"cid": "",
|
11
|
+
"phone": "",
|
12
|
+
"created-on": "",
|
13
|
+
"accounts": "15",
|
14
|
+
"company_name_url": "000-company-one",
|
15
|
+
"can_see_private": true,
|
16
|
+
"tags": [],
|
17
|
+
"zip": "90021",
|
18
|
+
"industryId": "",
|
19
|
+
"id": "999",
|
20
|
+
"last-changed-on": "2018-12-11T20:18:08Z",
|
21
|
+
"fax": "",
|
22
|
+
"address_two": "",
|
23
|
+
"name": "Company One",
|
24
|
+
"country": "United States",
|
25
|
+
"isowner": "1",
|
26
|
+
"industry": "",
|
27
|
+
"address_one": "1 First Avenue",
|
28
|
+
"countrycode": "US",
|
29
|
+
"collaborators": "2",
|
30
|
+
"city": "Los Angeles"
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
{
|
2
|
+
"STATUS": "OK",
|
3
|
+
"people": [
|
4
|
+
{
|
5
|
+
"permissions": {
|
6
|
+
"can-access-templates": false,
|
7
|
+
"can-add-projects": false,
|
8
|
+
"canManagePortfolio": false,
|
9
|
+
"can-manage-people": false,
|
10
|
+
"canAccessPortfolio": false
|
11
|
+
},
|
12
|
+
"avatar-url": "",
|
13
|
+
"last-changed-on": "2018-08-09T14:21:19Z",
|
14
|
+
"email-address": "",
|
15
|
+
"last-login": "",
|
16
|
+
"address-country": "",
|
17
|
+
"textFormat": "HTML",
|
18
|
+
"user-name": "",
|
19
|
+
"id": "",
|
20
|
+
"phone-number-fax": "",
|
21
|
+
"site-owner": false,
|
22
|
+
"address-city": "",
|
23
|
+
"company-name": "MCG Company",
|
24
|
+
"user-invited-date": "",
|
25
|
+
"user-type": "collaborator",
|
26
|
+
"phone-number-mobile": "",
|
27
|
+
"useShorthandDurations": false,
|
28
|
+
"address-zip": "",
|
29
|
+
"openId": "",
|
30
|
+
"address": {
|
31
|
+
"city": "",
|
32
|
+
"country": "",
|
33
|
+
"countrycode": "",
|
34
|
+
"zipcode": "",
|
35
|
+
"state": "",
|
36
|
+
"line1": "",
|
37
|
+
"line2": ""
|
38
|
+
},
|
39
|
+
"phone-number-office": "",
|
40
|
+
"im-handle": "",
|
41
|
+
"twoFactorAuthEnabled": false,
|
42
|
+
"tags": [],
|
43
|
+
"has-access-to-new-projects": false,
|
44
|
+
"last-active": "",
|
45
|
+
"im-service": "",
|
46
|
+
"deleted": false,
|
47
|
+
"notes": "",
|
48
|
+
"in-owner-company": true,
|
49
|
+
"user-invited-status": "PENDING",
|
50
|
+
"profile": "",
|
51
|
+
"userUUID": "",
|
52
|
+
"user-invited": "2",
|
53
|
+
"created-at": "2018-06-14T14:07:29Z",
|
54
|
+
"companyId": "",
|
55
|
+
"phone-number-home": "",
|
56
|
+
"profile-text": "",
|
57
|
+
"company-id": "",
|
58
|
+
"pid": "",
|
59
|
+
"phone-number-mobile-parts": {
|
60
|
+
"countryCode": "",
|
61
|
+
"prefix": "",
|
62
|
+
"phone": ""
|
63
|
+
},
|
64
|
+
"address-line-2": "",
|
65
|
+
"address-state": "",
|
66
|
+
"login-count": "0",
|
67
|
+
"address-line-1": "",
|
68
|
+
"administrator": false,
|
69
|
+
"email-alt-1": "",
|
70
|
+
"email-alt-2": "",
|
71
|
+
"email-alt-3": "",
|
72
|
+
"last-name": "User",
|
73
|
+
"title": "",
|
74
|
+
"first-name": "Demo 2",
|
75
|
+
"phone-number-office-ext": "",
|
76
|
+
"twitter": "",
|
77
|
+
"lengthOfDay": "8.0"
|
78
|
+
}
|
79
|
+
]
|
80
|
+
}
|