togglv9 0.1.0

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.
@@ -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