toggl_api 0.0.2

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 (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +48 -0
  7. data/Rakefile +1 -0
  8. data/lib/toggl_api.rb +7 -0
  9. data/lib/toggl_api/api/client.rb +42 -0
  10. data/lib/toggl_api/api/project.rb +46 -0
  11. data/lib/toggl_api/api/project_user.rb +38 -0
  12. data/lib/toggl_api/api/tag.rb +24 -0
  13. data/lib/toggl_api/api/task.rb +38 -0
  14. data/lib/toggl_api/api/time_entry.rb +73 -0
  15. data/lib/toggl_api/api/user.rb +46 -0
  16. data/lib/toggl_api/api/workspace.rb +36 -0
  17. data/lib/toggl_api/api/workspace_user.rb +32 -0
  18. data/lib/toggl_api/base.rb +39 -0
  19. data/lib/toggl_api/error.rb +8 -0
  20. data/lib/toggl_api/report.rb +30 -0
  21. data/lib/toggl_api/request.rb +100 -0
  22. data/lib/toggl_api/version.rb +3 -0
  23. data/test/base_test.rb +38 -0
  24. data/test/fixtures/authentication.json +44 -0
  25. data/test/fixtures/bulk_update_tasks.json +24 -0
  26. data/test/fixtures/bulk_update_time_entries.json +29 -0
  27. data/test/fixtures/client.json +11 -0
  28. data/test/fixtures/client_projects.json +21 -0
  29. data/test/fixtures/clients.json +15 -0
  30. data/test/fixtures/create_client.json +8 -0
  31. data/test/fixtures/create_project.json +13 -0
  32. data/test/fixtures/create_project_user.json +0 -0
  33. data/test/fixtures/create_tag.json +7 -0
  34. data/test/fixtures/create_task.json +10 -0
  35. data/test/fixtures/create_time_entry.json +13 -0
  36. data/test/fixtures/invite_users_to_workspace.json +12 -0
  37. data/test/fixtures/project.json +13 -0
  38. data/test/fixtures/project_users.json +18 -0
  39. data/test/fixtures/relations_of_workspace_and_user.json +22 -0
  40. data/test/fixtures/report_failure.json +8 -0
  41. data/test/fixtures/report_success.json +6 -0
  42. data/test/fixtures/reset_api_token.json +2 -0
  43. data/test/fixtures/signup.json +19 -0
  44. data/test/fixtures/start_time_entry.json +13 -0
  45. data/test/fixtures/stop_time_entry.json +13 -0
  46. data/test/fixtures/task.json +10 -0
  47. data/test/fixtures/time_entries.json +24 -0
  48. data/test/fixtures/time_entry.json +15 -0
  49. data/test/fixtures/update_client.json +9 -0
  50. data/test/fixtures/update_project.json +12 -0
  51. data/test/fixtures/update_project_user.json +0 -0
  52. data/test/fixtures/update_tag.json +7 -0
  53. data/test/fixtures/update_task.json +13 -0
  54. data/test/fixtures/update_time_entry.json +15 -0
  55. data/test/fixtures/update_user.json +31 -0
  56. data/test/fixtures/update_workspace_user.json +9 -0
  57. data/test/fixtures/workspace_clients.json +19 -0
  58. data/test/fixtures/workspace_projects.json +21 -0
  59. data/test/fixtures/workspace_tasks.json +29 -0
  60. data/test/fixtures/workspace_users.json +47 -0
  61. data/test/fixtures/workspaces.json +12 -0
  62. data/test/helper.rb +10 -0
  63. data/test/test_client.rb +51 -0
  64. data/test/test_project.rb +94 -0
  65. data/test/test_report.rb +53 -0
  66. data/test/test_tag.rb +30 -0
  67. data/test/test_task.rb +51 -0
  68. data/test/test_time_entry.rb +69 -0
  69. data/test/test_user.rb +53 -0
  70. data/test/test_workspace.rb +72 -0
  71. data/toggl_api.gemspec +30 -0
  72. metadata +260 -0
@@ -0,0 +1,36 @@
1
+ module Toggl
2
+ module Api
3
+ module Workspace
4
+
5
+ # *name*: (string, required)
6
+ # premium: If it's a pro workspace or not. Shows if someone is paying for the workspace or not (boolean, not required)
7
+ # at: timestamp that is sent in the response, indicates the time item was last updated
8
+
9
+ def workspaces
10
+ get "/workspaces"
11
+ end
12
+
13
+ def get_workspace_users(wid)
14
+ get "/workspaces/#{wid}/users"
15
+ end
16
+ alias :workspace_users :get_workspace_users
17
+
18
+ def get_workspace_clients(wid)
19
+ get "/workspaces/#{wid}/clients"
20
+ end
21
+ alias :workspace_clients :get_workspace_clients
22
+
23
+ # the token owner must be workspace admin
24
+ def get_workspace_projects(wid, active=true)
25
+ get "/workspaces/#{wid}/projects", {:active => active}
26
+ end
27
+ alias :workspace_projects :get_workspace_projects
28
+
29
+ def get_workspace_tasks(wid, active=true)
30
+ get "/workspaces/#{wid}/tasks", {:active => active}
31
+ end
32
+ alias :workspace_tasks :get_workspace_tasks
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ module Toggl
2
+ module Api
3
+ module WorkspaceUser
4
+
5
+ # id: workspace user id (integer)
6
+ # uid: user id of the workspace user (integer)
7
+ # admin: if user is workspace admin (boolean)
8
+ # active: if the workspace user has accepted the invitation to this workspace (boolean)
9
+ # invite_url: if user has not accepted the invitation the url for accepting his/her invitation is sent when the request is made by workspace_admin
10
+
11
+ def invite_users_to_workspace(wid, emails)
12
+ post "/workspaces/#{wid}/invite",{:emails => emails}
13
+ end
14
+
15
+ def update_workspace_user(wuid, options)
16
+ options = Hashie::Mash.new options
17
+ post "/workspace_users/#{wuid}",(options.key?(:workspace_user) ? options : {:workspace_user => options})
18
+ end
19
+
20
+ def delete_workspace_user(uid)
21
+ delete "/workspace_users/#{uid}"
22
+ end
23
+
24
+ #orkspace_user objects (the connection between user and workspace)
25
+ def get_relations_of_workspace_and_user(wid)
26
+ get "/workspaces/#{wid}/workspace_users"
27
+ end
28
+ alias :relations_of_workspace_and_user :get_relations_of_workspace_and_user
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ require 'toggl_api/request'
2
+ require 'toggl_api/api/client'
3
+ require 'toggl_api/api/project'
4
+ require 'toggl_api/api/project_user'
5
+ require 'toggl_api/api/tag'
6
+ require 'toggl_api/api/task'
7
+ require 'toggl_api/api/time_entry'
8
+ require 'toggl_api/api/user'
9
+ require 'toggl_api/api/workspace'
10
+ require 'toggl_api/api/workspace_user'
11
+
12
+ module Toggl
13
+ class Base
14
+
15
+ include Toggl::Request
16
+ include Toggl::Api::Client
17
+ include Toggl::Api::Project
18
+ include Toggl::Api::ProjectUser
19
+ include Toggl::Api::Tag
20
+ include Toggl::Api::Task
21
+ include Toggl::Api::TimeEntry
22
+ include Toggl::Api::User
23
+ include Toggl::Api::Workspace
24
+ include Toggl::Api::WorkspaceUser
25
+
26
+ APIVERSION = "v8"
27
+
28
+ def initialize(username, pass='api_token')
29
+ @username,@pass = username,pass
30
+ end
31
+
32
+ private
33
+
34
+ def basic_path(path)
35
+ path = "/api/#{APIVERSION}#{path}" unless path =~ /api/
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,8 @@
1
+ module Toggl
2
+ class Unauthorized < StandardError; end
3
+ class Forbidden < StandardError; end
4
+ class BadRequest < StandardError; end
5
+ class Unavailable < StandardError; end
6
+ class NotFound < StandardError; end
7
+ class InternalServerError < StandardError; end
8
+ end
@@ -0,0 +1,30 @@
1
+ require 'toggl_api/request'
2
+
3
+ module Toggl
4
+ class Report
5
+
6
+ include Toggl::Request
7
+
8
+ APIVERSION = "v2"
9
+
10
+ def initialize(token)
11
+ @username,@pass = token,"api_token"
12
+ end
13
+
14
+ #reports
15
+ %w[weekly details summary].each do |method|
16
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
17
+ def #{method}(workspace_id, params={})
18
+ request(:get, '/#{method}', params.merge({:workspace_id => workspace_id,:user_agent => user_agent}))
19
+ end
20
+ RUBY
21
+ end
22
+
23
+ private
24
+
25
+ def basic_path(path)
26
+ path = "/reports/api/#{APIVERSION}#{path}" unless path =~ /reports/
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,100 @@
1
+ require 'toggl_api/error'
2
+
3
+ module Toggl
4
+ module Request
5
+
6
+ ENDPOINT = "https://www.toggl.com"
7
+
8
+ attr_writer :user_agent, :connection_options
9
+
10
+ def user_agent
11
+ @user_agent ||= "Toggl Api Ruby Gem #{Toggl::VERSION}"
12
+ end
13
+
14
+ def connection_options
15
+ @connection_options ||= {
16
+ :headers => {
17
+ :accept => 'application/json',
18
+ :user_agent => user_agent,
19
+ 'Content-Type' => 'application/json'
20
+ }
21
+ }
22
+ end
23
+
24
+ #perform http request
25
+ %w[get delete].each do |method|
26
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
27
+ def #{method}(path, params={})
28
+ request(:#{method}, path, params)
29
+ end
30
+ RUBY
31
+ end
32
+
33
+ %w[post put].each do |method|
34
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
35
+ def #{method}(path, params={})
36
+ request(:#{method}, path, MultiJson.dump(params))
37
+ end
38
+ RUBY
39
+ end
40
+
41
+ private
42
+
43
+ def request(method, path, params={})
44
+ handle_response connection.send(method.to_sym, basic_path(path), params)
45
+ rescue Faraday::Error::ClientError
46
+ raise TogglApi::Error
47
+ end
48
+
49
+ def connection
50
+ @connection ||= Faraday.new(ENDPOINT,connection_options) do |faraday|
51
+ faraday.request :url_encoded
52
+ faraday.adapter Faraday.default_adapter
53
+ faraday.basic_auth @username, @pass
54
+ end
55
+ end
56
+
57
+ def handle_response(response)
58
+ raise_errors(response)
59
+ data = mash(MultiJson.load(response.body))
60
+ (data.is_a?(Hash) && data.key?('data')) ? data['data'] : data
61
+ end
62
+
63
+ def raise_errors(response)
64
+ message = "(#{response.status}): #{response.body}"
65
+ case response.status.to_i
66
+ when 400
67
+ raise BadRequest, message
68
+ when 401
69
+ raise Unauthorized, message
70
+ when 403
71
+ raise Forbidden, message
72
+ when 404
73
+ raise NotFound, message
74
+ when 500
75
+ raise InternalServerError, message
76
+ when 502..503
77
+ raise Unavailable, message
78
+ end
79
+ end
80
+
81
+ def mash(obj)
82
+ if obj.is_a?(Array)
83
+ obj.map { |item| make_mash_with_consistent_hash(item) }
84
+ elsif obj.is_a?(Hash)
85
+ make_mash_with_consistent_hash(obj)
86
+ else
87
+ obj
88
+ end
89
+ end
90
+
91
+ def make_mash_with_consistent_hash(obj)
92
+ m = Hashie::Mash.new(obj)
93
+ def m.hash
94
+ inspect.hash
95
+ end
96
+ return m
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,3 @@
1
+ module Toggl
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path '../helper.rb', __FILE__
2
+
3
+ class baseTest < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @base = Toggl::Base.new('abc','123')
7
+ end
8
+
9
+ def test_authorization_header
10
+ assert_match /Basic/,@base.get("/api/v8/me")[:request_headers]["Authorization"]
11
+ end
12
+
13
+ def test_get_method
14
+ @base.stub :request, Faraday::Response.new do
15
+ assert_kind_of Faraday::Response, @base.get("/api/v8/me")
16
+ end
17
+ end
18
+
19
+ def test_post_method
20
+ @base.stub :request, Faraday::Response.new do
21
+ assert_kind_of Faraday::Response, @base.post("/api/v8/me")
22
+ end
23
+ end
24
+
25
+ def test_put_method
26
+ @base.stub :request, Faraday::Response.new do
27
+ assert_kind_of Faraday::Response, @base.put("/api/v8/me")
28
+ end
29
+ end
30
+
31
+ def test_delete_method
32
+ @base.stub :request, Faraday::Response.new do
33
+ assert_kind_of Faraday::Response, @base.delete("/api/v8/me")
34
+ end
35
+ end
36
+
37
+ end
38
+
@@ -0,0 +1,44 @@
1
+ {
2
+ "since":1361780172,
3
+ "data": {
4
+ "id":123,
5
+ "api_token":"1971800d4d82861d8f2c1651fea4d212",
6
+ "default_wid":777,
7
+ "email":"john.doe@gmail.com",
8
+ "fullname":"John Doe",
9
+ "jquery_timeofday_format":"h:i A",
10
+ "jquery_date_format":"m/d/Y",
11
+ "timeofday_format":"h:mm A",
12
+ "date_format":"MM/DD/YYYY",
13
+ "store_start_and_stop_time":true,
14
+ "beginning_of_week":1,
15
+ "language":"en_US",
16
+ "image_url":"https://www.toggl.com/images/profile.png",
17
+ "new_blog_post":{},
18
+ "projects": [
19
+ {
20
+ "id":90123,
21
+ "wid":777,
22
+ "name":"Our best project",
23
+ "billable":true,
24
+ "active":true,
25
+ "at":"2013-02-12T09:47:57+00:00"
26
+ }
27
+ ],
28
+ "tags": [
29
+ {
30
+ "id":238526,
31
+ "wid":777,
32
+ "name":"billed"
33
+ }
34
+ ],
35
+ "tasks": [],
36
+ "workspaces": [
37
+ {
38
+ "id":777,"name":"John's WS","at":"2012-11-28T11:56:49+00:00"
39
+ }
40
+ ],
41
+ "clients": []
42
+ }
43
+ }
44
+
@@ -0,0 +1,24 @@
1
+ {
2
+ "data": [
3
+ {
4
+ "name":"A new task",
5
+ "id":1335076912,
6
+ "wid":888,
7
+ "pid":777,
8
+ "active":false,
9
+ "at":"2013-02-26T15:09:52+00:00",
10
+ "estimated_seconds":3600,
11
+ "uname": "John Swift",
12
+ "done_seconds": 1200
13
+ }, {
14
+ "name":"Another task",
15
+ "id":1335076911,
16
+ "wid":888,
17
+ "pid":777,
18
+ "active":false,
19
+ "at":"2013-02-26T15:09:52+00:00",
20
+ "estimated_seconds":3600,
21
+ "done_seconds": 10
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,29 @@
1
+ { "data":[
2
+ {
3
+ "id":436694100,
4
+ "guid":"dfc88541-f3b0-bffe-fa2e-46a09fa97664",
5
+ "wid":777,
6
+ "pid":20123718,
7
+ "billable":true,
8
+ "start":"2013-08-01T10:46:00",
9
+ "stop":"2013-08-01T11:46:02",
10
+ "duration":3602,
11
+ "description":"Development",
12
+ "tags":["billed","poductive","overhours"],
13
+ "duronly":false,
14
+ "at":"2013-08-01T12:04:57"
15
+ },{
16
+ "id":436694101,
17
+ "guid":"ce3c2409-e624-64e2-6742-c623ff284091",
18
+ "wid":777,
19
+ "billable":false,
20
+ "start":"2013-08-01T11:11:00",
21
+ "stop":"2013-08-01T11:46:04",
22
+ "duration":2104,
23
+ "description":"Meeting with the client",
24
+ "tags":["billed","poductive","holiday"],
25
+ "duronly":false,
26
+ "at":"2013-08-01T11:46:08"
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "data": {
3
+ "id":1239455,
4
+ "wid":777,
5
+ "name":"Very Big Company",
6
+ "at":"2013-02-26T08:45:28+00:00",
7
+ "notes": "Contact: John Jacob Jingleheimer Schmidt",
8
+ "hrate": 12,
9
+ "cur": "AUD"
10
+ }
11
+ }
@@ -0,0 +1,21 @@
1
+ [
2
+ {
3
+ "id":909,
4
+ "wid":777,
5
+ "cid":987,
6
+ "name":"Very lucrative project",
7
+ "billable":false,
8
+ "is_private":true,
9
+ "active":true,
10
+ "at":"2013-03-06T09:15:18+00:00"
11
+ },{
12
+ "id":32143,
13
+ "wid":777,
14
+ "cid":987,
15
+ "name":"Factory server infrastructure",
16
+ "billable":true,
17
+ "is_private":true,
18
+ "active":true,
19
+ "at":"2013-03-06T09:16:06+00:00"
20
+ }
21
+ ]
@@ -0,0 +1,15 @@
1
+ [
2
+ {
3
+ "id":1239455,
4
+ "wid":777,
5
+ "name":"Very Big Company",
6
+ "notes":"something about the client",
7
+ "at":"2013-02-26T08:55:28+00:00"
8
+ }, {
9
+ "id":1239456,
10
+ "wid":777,
11
+ "name":"Small Startup",
12
+ "notes":"Really cool people",
13
+ "at":"2013-03-26T08:55:28+00:00"
14
+ }
15
+ ]