togglv9 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,114 @@
1
+ module TogglV9
2
+ class API
3
+
4
+ ##
5
+ # ---------
6
+ # :section: Projects
7
+ #
8
+ # See Toggl {Projects}[https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md]
9
+ #
10
+ # name : The name of the project
11
+ # (string, *required*, unique for client and workspace)
12
+ # wid : workspace ID, where the project will be saved
13
+ # (integer, *required*)
14
+ # cid : client ID
15
+ # (integer, not required)
16
+ # active : whether the project is archived or not
17
+ # (boolean, by default true)
18
+ # is_private : whether project is accessible for only project users or for all workspace users
19
+ # (boolean, default true)
20
+ # template : whether the project can be used as a template
21
+ # (boolean, not required)
22
+ # template_id : id of the template project used on current project's creation
23
+ # billable : whether the project is billable or not
24
+ # (boolean, default true, available only for pro workspaces)
25
+ # auto_estimates : whether the estimated hours is calculated based on task estimations or is fixed manually
26
+ # (boolean, default false, not required, premium functionality)
27
+ # estimated_hours : if auto_estimates is true then the sum of task estimations is returned, otherwise user inserted hours
28
+ # (integer, not required, premium functionality)
29
+ # at : timestamp that is sent in the response for PUT, indicates the time task was last updated
30
+ # color : id of the color selected for the project
31
+ # rate : hourly rate of the project
32
+ # (float, not required, premium functionality)
33
+ # created_at : timestamp indicating when the project was created (UTC time), read-only
34
+ # ---------
35
+
36
+ ##
37
+ # :category: Projects
38
+ #
39
+ # Public: Create a new project
40
+ #
41
+ # params - The Hash used to create the project (default: {})
42
+ # :name - The name of the project (string, required, unique for client and workspace)
43
+ # :wid - workspace ID, where the project will be saved (integer, required)
44
+ # :cid - client ID (integer, not required)
45
+ # :active - whether the project is archived or not (boolean, by default true)
46
+ # :is_private - whether project is accessible for only project users or for all workspace users (boolean, default true)
47
+ # :template - whether the project can be used as a template (boolean, not required)
48
+ # :template_id - id of the template project used on current project's creation
49
+ # :billable - whether the project is billable or not (boolean, default true, available only for pro workspaces)
50
+ # :auto_estimates - whether the estimated hours is calculated based on task estimations or is fixed manually (boolean, default false, not required, premium functionality)
51
+ # :estimated_hours - if auto_estimates is true then the sum of task estimations is returned, otherwise user inserted hours (integer, not required, premium functionality)
52
+ # :at - timestamp that is sent in the response for PUT, indicates the time task was last updated
53
+ # :color - id of the color selected for the project
54
+ # :rate - hourly rate of the project (float, not required, premium functionality)
55
+ # :created_at - timestamp indicating when the project was created (UTC time), read-only
56
+ #
57
+ # Examples
58
+ #
59
+ # toggl.create_project(1060392, { :name => 'My project' })
60
+ # => {"id"=>10918774,
61
+ # "wid"=>1060392,
62
+ # "name"=>"project5",
63
+ # "billable"=>false,
64
+ # "is_private"=>true,
65
+ # "active"=>true,
66
+ # "template"=>false,
67
+ # "at"=>"2015-08-18T10:03:51+00:00",
68
+ # "color"=>"5",
69
+ # "auto_estimates"=>false}
70
+ #
71
+ # Returns a +Hash+ representing the newly created Project.
72
+ #
73
+ # See Toggl {Create Project}[https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#create-project]
74
+ def create_project(workspace_id, params)
75
+ requireParams(params, ['name'])
76
+ params['active'] = true unless params.key?('active')
77
+ post "workspaces/#{workspace_id}/projects", params
78
+ end
79
+
80
+ # [Get project data](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#get-project-data)
81
+ def get_project(workspace_id, project_id)
82
+ get "workspaces/#{workspace_id}/projects/#{project_id}"
83
+ end
84
+
85
+ # [Update project data](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#update-project-data)
86
+ def update_project(workspace_id, project_id, params)
87
+ put "workspaces/#{workspace_id}/projects/#{project_id}", params
88
+ end
89
+
90
+ # [Delete a project](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#delete-a-project)
91
+ def delete_project(workspace_id, project_id)
92
+ delete "workspaces/#{workspace_id}/projects/#{project_id}"
93
+ end
94
+
95
+ # [Get project users](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#get-project-users)
96
+ def get_project_users(workspace_id, project_id)
97
+ qs = "?project_ids=#{project_id}"
98
+ get "workspaces/#{workspace_id}/project_users#{qs}"
99
+ end
100
+
101
+ # [Get project tasks](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#get-project-tasks)
102
+ def get_project_tasks(workspace_id, project_id)
103
+ get "workspaces/#{workspace_id}/tasks", { 'pid': project_id }
104
+ end
105
+
106
+ # [Delete multiple projects](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#delete-multiple-projects)
107
+ def delete_projects(workspace_id, project_ids)
108
+ return if project_ids.nil?
109
+ project_ids.each do |project_id|
110
+ delete_project(workspace_id, project_id)
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,25 @@
1
+ module TogglV9
2
+ class API
3
+
4
+ ##
5
+ # ---------
6
+ # :section: Tags
7
+ #
8
+ # name : The name of the tag (string, required, unique in workspace)
9
+ # wid : workspace ID, where the tag will be used (integer, required)
10
+
11
+ def create_tag(workspace_id, params)
12
+ requireParams(params, ['name'])
13
+ post "workspaces/#{workspace_id}/tags", params
14
+ end
15
+
16
+ # ex: update_tag(12345, { :name => "same tame game" })
17
+ def update_tag(workspace_id, tag_id, params)
18
+ put "workspaces/#{workspace_id}/tags/#{tag_id}", params
19
+ end
20
+
21
+ def delete_tag(workspace_id, tag_id)
22
+ delete "workspaces/#{workspace_id}/tags/#{tag_id}"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ module TogglV9
2
+ class API
3
+
4
+ ##
5
+ # ---------
6
+ # :section: Tasks
7
+ #
8
+ # NOTE: Tasks are available only for pro workspaces.
9
+ #
10
+ # name : The name of the task (string, required, unique in project)
11
+ # pid : project ID for the task (integer, required)
12
+ # wid : workspace ID, where the task will be saved
13
+ # (integer, project's workspace id is used when not supplied)
14
+ # uid : user ID, to whom the task is assigned to (integer, not required)
15
+ # estimated_seconds : estimated duration of task in seconds (integer, not required)
16
+ # active : whether the task is done or not (boolean, by default true)
17
+ # at : timestamp that is sent in the response for PUT, indicates the time task was last updated
18
+ # -- Additional fields --
19
+ # done_seconds : duration (in seconds) of all the time entries registered for this task
20
+ # uname : full name of the person to whom the task is assigned to
21
+
22
+ def create_task(workspace_id, project_id, params)
23
+ requireParams(params, ['name'])
24
+ post "workspaces/#{workspace_id}/projects/#{project_id}/tasks", params
25
+ end
26
+
27
+ def get_task(workspace_id, project_id, task_id)
28
+ get "workspaces/#{workspace_id}/projects/#{project_id}tasks/#{task_id}"
29
+ end
30
+
31
+ # ex: update_task(1894675, { :active => true, :estimated_seconds => 4500, :fields => "done_seconds,uname"})
32
+ def update_task(workspace_id, project_id, task_id, params)
33
+ put "workspaces/#{workspace_id}/projects/#{project_id}/tasks/#{task_id}", params
34
+ end
35
+
36
+ def delete_task(workspace_id, project_id, task_id)
37
+ delete "workspaces/#{workspace_id}/projects/#{project_id}/tasks/#{task_id}"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,114 @@
1
+ module TogglV9
2
+ class API
3
+
4
+ ##
5
+ # ---------
6
+ # :section: Time Entries
7
+ #
8
+ # https://github.com/toggl/toggl_api_docs/blob/master/chapters/time_entries.md
9
+ #
10
+ # description : (string, strongly suggested to be used)
11
+ # wid : workspace ID (integer, required if pid or tid not supplied)
12
+ # pid : project ID (integer, not required)
13
+ # tid : task ID (integer, not required)
14
+ # billable : (boolean, not required, default false, available for pro workspaces)
15
+ # start : time entry start time (string, required, ISO 8601 date and time)
16
+ # stop : time entry stop time (string, not required, ISO 8601 date and time)
17
+ # duration : time entry duration in seconds. If the time entry is currently running,
18
+ # the duration attribute contains a negative value,
19
+ # denoting the start of the time entry in seconds since epoch (Jan 1 1970).
20
+ # The correct duration can be calculated as current_time + duration,
21
+ # where current_time is the current time in seconds since epoch. (integer, required)
22
+ # created_with : the name of your client app (string, required)
23
+ # tags : a list of tag names (array of strings, not required)
24
+ # duronly : should Toggl show the start and stop time of this time entry? (boolean, not required)
25
+ # at : timestamp that is sent in the response, indicates the time item was last updated
26
+
27
+ def create_time_entry(workspace_id, params)
28
+ params['created_with'] = TogglV9::NAME unless params.has_key?('created_with')
29
+ requireParams(params, ['wid', 'start', 'duration', 'created_with'])
30
+ post "workspaces/#{workspace_id}/time_entries", params
31
+ end
32
+
33
+ def start_time_entry(workspace_id, params)
34
+ params['created_with'] = TogglV9::NAME unless params.has_key?('created_with')
35
+ requireParams(params, ['workspace_id'])
36
+ params["start"] = iso8601(Time.now)
37
+ params["duration"] = -1
38
+ post "workspaces/#{workspace_id}/time_entries", params
39
+ end
40
+
41
+ def stop_time_entry(workspace_id, time_entry_id)
42
+ patch "workspaces/#{workspace_id}/time_entries/#{time_entry_id}/stop", {}
43
+ end
44
+
45
+ def get_time_entry(time_entry_id)
46
+ get "me/time_entries/#{time_entry_id}"
47
+ end
48
+
49
+ def get_current_time_entry
50
+ get "me/time_entries/current"
51
+ end
52
+
53
+ def update_time_entry(workspace_id, time_entry_id, params)
54
+ put "workspaces/#{workspace_id}/time_entries/#{time_entry_id}", params
55
+ end
56
+
57
+ def delete_time_entry(workspace_id, time_entry_id)
58
+ delete "workspaces/#{workspace_id}/time_entries/#{time_entry_id}"
59
+ end
60
+
61
+ def iso8601(timestamp)
62
+ return nil if timestamp.nil?
63
+ if timestamp.is_a?(DateTime) or timestamp.is_a?(Date) or timestamp.is_a?(Time)
64
+ formatted_ts = timestamp.iso8601
65
+ elsif timestamp.is_a?(String)
66
+ formatted_ts = DateTime.parse(timestamp).iso8601
67
+ else
68
+ raise ArgumentError, "Can't convert #{timestamp.class} to ISO-8601 Date/Time"
69
+ end
70
+ return formatted_ts.sub('+00:00', 'Z')
71
+ end
72
+
73
+ def get_time_entries(dates = {})
74
+ start_date = dates[:start_date]
75
+ end_date = dates[:end_date]
76
+ params = []
77
+ start_date = Time.now - 9 * 24 * 60 * 60 if start_date.nil?
78
+ end_date = Time.now if end_date.nil?
79
+ params.push("start_date=#{iso8601(start_date)}")
80
+ params.push("end_date=#{iso8601(end_date)}")
81
+ get "me/time_entries%s" % [params.empty? ? "" : "?#{params.join('&')}"]
82
+ end
83
+
84
+ # FIXME: v9 PATCH
85
+ # Example params: {'tags' =>['billed','productive'], 'tag_action' => 'add'}
86
+ # tag_action can be 'add' or 'remove'
87
+ def update_time_entries_tags(workspace_id, time_entry_ids, params)
88
+ return if time_entry_ids.nil?
89
+ requireParams(params, ['tags', 'tag_action'])
90
+ patch "workspaces/#{workspace_id}/time_entries/#{time_entry_ids.join(',')}", params
91
+ end
92
+
93
+ # TEMPORARY FIXED version of API issue
94
+ # see https://github.com/toggl/toggl_api_docs/issues/20 for more info
95
+ def update_time_entries_tags_fixed(workspace_id, time_entry_ids, params)
96
+ time_entries = update_time_entries_tags(workspace_id, time_entry_ids, params)
97
+ return time_entries if params['tag_action'] == 'add'
98
+
99
+ time_entries_for_removing_all_tags_ids = []
100
+ [].push(time_entries).flatten.map! do |time_entry|
101
+ unless time_entry['tags'].nil?
102
+ time_entry['tags'] = time_entry['tags'] - params['tags']
103
+ time_entries_for_removing_all_tags_ids << time_entry['id'] if time_entry['tags'].empty?
104
+ end
105
+ time_entry
106
+ end
107
+
108
+ remove_params = {'tags' => []}
109
+ put "time_entries/#{time_entries_for_removing_all_tags_ids.join(',')}", { 'time_entry' => remove_params } unless time_entries_for_removing_all_tags_ids.empty?
110
+
111
+ time_entries
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,43 @@
1
+ require_relative 'clients'
2
+ require_relative 'dashboard'
3
+ require_relative 'project_users'
4
+ require_relative 'projects'
5
+ require_relative 'tags'
6
+ require_relative 'tasks'
7
+ require_relative 'time_entries'
8
+ require_relative 'users'
9
+ require_relative 'version'
10
+ require_relative 'workspaces'
11
+
12
+ module TogglV9
13
+ TOGGL_API_URL = 'https://api.track.toggl.com/api/'
14
+
15
+ class API
16
+ include TogglV9::Connection
17
+
18
+ TOGGL_API_V9_URL = TOGGL_API_URL + 'v9/'
19
+
20
+ attr_reader :conn
21
+
22
+ def initialize(username=nil, password=API_TOKEN, opts={})
23
+ debug(false)
24
+ if username.nil? && password == API_TOKEN
25
+ toggl_api_file = File.join(Dir.home, TOGGL_FILE)
26
+ # logger.debug("toggl_api_file = #{toggl_api_file}")
27
+ if File.exist?(toggl_api_file) then
28
+ username = IO.read(toggl_api_file).strip
29
+ else
30
+ raise "Expecting one of:\n" +
31
+ " 1) api_token in file #{toggl_api_file}, or\n" +
32
+ " 2) parameter: (api_token), or\n" +
33
+ " 3) parameters: (username, password).\n" +
34
+ "\n\tSee https://github.com/kanet77/togglv9#togglv9api" +
35
+ "\n\tand https://github.com/toggl/toggl_api_docs/blob/master/chapters/authentication.md"
36
+ end
37
+ end
38
+
39
+ @conn = TogglV9::Connection.open(username, password,
40
+ TOGGL_API_V9_URL, opts)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,74 @@
1
+ module TogglV9
2
+ class API
3
+
4
+ ##
5
+ # ---------
6
+ # :section: Users
7
+ #
8
+ # api_token : (string)
9
+ # default_wid : default workspace id (integer)
10
+ # email : (string)
11
+ # jquery_timeofday_format : (string)
12
+ # jquery_date_format : (string)
13
+ # timeofday_format : (string)
14
+ # date_format : (string)
15
+ # store_start_and_stop_time : whether start and stop time are saved on time entry (boolean)
16
+ # beginning_of_week : (integer, Sunday=0)
17
+ # language : user's language (string)
18
+ # image_url : url with the user's profile picture(string)
19
+ # sidebar_piechart : should a piechart be shown on the sidebar (boolean)
20
+ # at : timestamp of last changes
21
+ # new_blog_post : an object with toggl blog post title and link
22
+
23
+ def me(all=nil)
24
+ # NOTE: response['since'] is discarded because it is outside response['data']
25
+ # (See TogglV9::API#get in lib/togglv9.rb)
26
+ get "me%s" % [all.nil? ? "" : "?with_related_data=#{all}"]
27
+ end
28
+
29
+ def my_clients(user=nil)
30
+ user = me(all=true) if user.nil?
31
+ user['clients'] || {}
32
+ end
33
+
34
+ def my_projects(user=nil)
35
+ user = me(all=true) if user.nil?
36
+ return {} unless user['projects']
37
+ projects = user['projects']
38
+ projects.delete_if { |p| p['server_deleted_at'] }
39
+ end
40
+
41
+ def my_deleted_projects(user=nil)
42
+ user = me(all=true) if user.nil?
43
+ return {} unless user['projects']
44
+ projects = user['projects']
45
+ projects.keep_if { |p| p['server_deleted_at'] }
46
+ end
47
+
48
+ def my_tags(user=nil)
49
+ user = me(all=true) if user.nil?
50
+ user['tags'] || {}
51
+ end
52
+
53
+ def my_tasks(user=nil)
54
+ user = me(all=true) if user.nil?
55
+ user['tasks'] || {}
56
+ end
57
+
58
+ def my_time_entries(user=nil)
59
+ user = me(all=true) if user.nil?
60
+ user['time_entries'] || {}
61
+ end
62
+
63
+ def my_workspaces(user=nil)
64
+ user = me(all=true) if user.nil?
65
+ user['workspaces'] || {}
66
+ end
67
+
68
+ def create_user(params)
69
+ params['created_with'] = TogglV9::NAME unless params.has_key?('created_with')
70
+ requireParams(params, ['email', 'password', 'timezone', 'created_with'])
71
+ post "signup", params
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,4 @@
1
+ module TogglV9
2
+ # :section:
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,43 @@
1
+ module TogglV9
2
+ class API
3
+
4
+ ##
5
+ # ---------
6
+ # :section: Workspaces
7
+ #
8
+ # name : (string, required)
9
+ # premium : If it's a pro workspace or not.
10
+ # Shows if someone is paying for the workspace or not (boolean, not required)
11
+ # at : timestamp that is sent in the response, indicates the time item was last updated
12
+
13
+ def workspaces
14
+ get "me/workspaces"
15
+ end
16
+
17
+ def clients(workspace_id)
18
+ get "workspaces/#{workspace_id}/clients"
19
+ end
20
+
21
+ def projects(workspace_id, params={})
22
+ active = params.has_key?(:active) ? "?active=#{params[:active]}" : ""
23
+ get "workspaces/#{workspace_id}/projects#{active}"
24
+ end
25
+
26
+ def users(organization_id, workspace_id)
27
+ get "organizations/#{organization_id}/workspaces/#{workspace_id}/workspace_users"
28
+ end
29
+
30
+ def tasks(workspace_id, params={})
31
+ active = params.has_key?(:active) ? "?active=#{params[:active]}" : ""
32
+ get "workspaces/#{workspace_id}/tasks#{active}"
33
+ end
34
+
35
+ def tags(workspace_id)
36
+ get "workspaces/#{workspace_id}/tags"
37
+ end
38
+
39
+ def leave_workspace(workspace_id)
40
+ delete "workspaces/#{workspace_id}/leave"
41
+ end
42
+ end
43
+ end
data/lib/togglv9.rb ADDED
@@ -0,0 +1,13 @@
1
+ require_relative 'togglv9/version'
2
+
3
+ require_relative 'togglv9/connection'
4
+
5
+ require_relative 'togglv9/togglv9'
6
+ require_relative 'reportsv2'
7
+
8
+ # :mode => :compat will convert symbols to strings
9
+ Oj.default_options = { :mode => :compat }
10
+
11
+ module TogglV9
12
+ NAME = "TogglV9 v#{TogglV9::VERSION}"
13
+ end
data/scripts/dump.sh ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ curl https://api.track.toggl.com/api/v9/organizations/${ORGANIZATION_ID}/workspaces/${WORKSPACE_ID}/workspace_users \
4
+ -H "Content-Type: application/json" \
5
+ -u $TOGGL_API_TOKEN:api_token