teamwork_api 0.1.0 → 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.
- 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
|
+
}
|