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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +11 -1
  4. data/.travis.yml +14 -1
  5. data/CHANGELOG.md +14 -0
  6. data/Gemfile +4 -2
  7. data/Gemfile.lock +65 -10
  8. data/Guardfile +12 -0
  9. data/README.md +5 -5
  10. data/Rakefile +2 -0
  11. data/lib/teamwork_api.rb +3 -0
  12. data/lib/teamwork_api/api/companies.rb +4 -0
  13. data/lib/teamwork_api/api/params.rb +18 -11
  14. data/lib/teamwork_api/api/people.rb +52 -29
  15. data/lib/teamwork_api/api/project_owner.rb +6 -1
  16. data/lib/teamwork_api/api/projects.rb +70 -47
  17. data/lib/teamwork_api/api/task_lists.rb +8 -4
  18. data/lib/teamwork_api/client.rb +24 -20
  19. data/lib/teamwork_api/error.rb +7 -1
  20. data/lib/teamwork_api/version.rb +3 -1
  21. data/spec/fixtures/companies.json +64 -0
  22. data/spec/fixtures/company.json +32 -0
  23. data/spec/fixtures/create_project.json +4 -0
  24. data/spec/fixtures/create_task_list.json +4 -0
  25. data/spec/fixtures/delete.json +3 -0
  26. data/spec/fixtures/people.json +80 -0
  27. data/spec/fixtures/person.json +77 -0
  28. data/spec/fixtures/project.json +68 -0
  29. data/spec/fixtures/project_owner.json +91 -0
  30. data/spec/fixtures/projects.json +135 -0
  31. data/spec/fixtures/task_list.json +18 -0
  32. data/spec/fixtures/task_lists.json +22 -0
  33. data/spec/fixtures/update.json +3 -0
  34. data/spec/spec_helper.rb +60 -7
  35. data/spec/teamwork_api/api/companies_spec.rb +69 -0
  36. data/spec/teamwork_api/api/people_spec.rb +78 -0
  37. data/spec/teamwork_api/api/project_owner_spec.rb +35 -0
  38. data/spec/teamwork_api/api/projects_spec.rb +117 -0
  39. data/spec/teamwork_api/api/task_lists_spec.rb +98 -0
  40. data/spec/teamwork_api/client_spec.rb +202 -0
  41. data/teamwork_api.gemspec +10 -2
  42. metadata +116 -8
  43. 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
- :description,
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
- response = put "projects/#{project_id}.json", project: args
54
- response['id']
80
+ put "projects/#{project_id}.json", project: args
55
81
  end
56
82
 
57
83
  def project(project_id, args = {})
58
- if args.present?
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
- response = get '/projects.json'
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['tasklist']
32
+ response.body['todo-list']
29
33
  end
30
34
 
31
35
  def task_lists
@@ -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 = connection.send(method.to_sym, path, params)
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(response.env[:body], response.env)
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.new(response.env[:body])
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
@@ -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)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamworkApi
2
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
3
5
  end
@@ -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,4 @@
1
+ {
2
+ "id": "323605",
3
+ "STATUS": "OK"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "TASKLISTID": "1234",
3
+ "STATUS": "OK"
4
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "STATUS": "OK"
3
+ }
@@ -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
+ }