timestamp_api 0.5.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a0f32becb73b472f08339084946177bd46c4e91
4
- data.tar.gz: 6231f1d36873b7467d6d5d70d4d2ea1db26e3e74
3
+ metadata.gz: 67c11519366433b792e43a3d44a6a2dae38e6b2a
4
+ data.tar.gz: 72c994d54a419b40ba8bc14bb7459edba86b18e8
5
5
  SHA512:
6
- metadata.gz: 84bc0fe028acd831ee41d3e1f81d7c11e78a807974fcae420ab2f382fb808ea9bb112d4b1e90b8dce21b7f71908ed1a1d4e167fb39f5904a5774c0ed4a7e73ad
7
- data.tar.gz: 71a13d05744b67fc07ec4f13ce5bc50135c9428a731b50157105ed7dfecbd67e27eac8383734f97124dd03c52e346d402b1e9dc73b24d3767946ef0a33899056
6
+ metadata.gz: 7e743c9cbeb2fac5c20a97895f9fec04f6c0636a73fe3ddedd070ec794fc126146bbcd775764d79ea2008378e0256234c7214dcbaaf3fa3bb5306c2999719604
7
+ data.tar.gz: b4dede14115223f3445e1d86e987cad5fa018b772b91332bd1afe2f819bece132b722abc0e8789bad132d174a2292b20fee9c94045da57f00c53e182f24dc061
data/README.md CHANGED
@@ -27,47 +27,112 @@ Or install it yourself as:
27
27
 
28
28
  ## Usage
29
29
 
30
- Configure your Timestamp API key by setting environment variable `TIMESTAMP_API_KEY` or manually:
30
+ Configure your Timestamp API key by setting environment variable `TIMESTAMP_API_KEY`:
31
+ ```shell
32
+ $ TIMESTAMP_API_KEY="YOUR_API_KEY" bin/console
33
+ ```
34
+
35
+ Or set it manually from the console:
36
+ ```ruby
37
+ TimestampAPi.api_key = "YOUR_API_KEY"
38
+ ```
39
+
40
+ #### Clients
41
+
42
+ List clients:
31
43
  ```ruby
32
- TimestampAPi.api_key = "YOUR_TIMESTAMP_API_KEY"
44
+ TimestampAPI::Client.all # => Returns all clients
45
+ ```
46
+
47
+ Find a given client:
48
+ ```ruby
49
+ client = TimestampAPI::Client.find(123)
50
+
51
+ client.name # => "My beloved customer"
33
52
  ```
34
53
 
35
54
  #### Projects
36
55
 
37
- List all projects:
56
+ List projects:
38
57
  ```ruby
39
- TimestampAPI::Project.all
58
+ TimestampAPI::Project.all # => Returns all projects
40
59
  ```
41
60
 
42
61
  Find a given project:
43
62
  ```ruby
44
63
  project = TimestampAPI::Project.find(123)
45
64
 
46
- project.name # => "My awesome project"
65
+ project.name # => "My awesome project"
66
+ project.client.name # => "My beloved customer"
67
+ project.enter_time(123, Date.today, 60) # => Creates a 60 minutes time entry for today on task 123 and returns the created TimeEntry
47
68
  ```
48
69
 
49
- #### Clients
70
+ #### Users
50
71
 
51
- List all clients:
72
+ List users:
52
73
  ```ruby
53
- TimestampAPI::Client.all
74
+ TimestampAPI::User.all # => Returns all users
54
75
  ```
55
76
 
56
- Find a given client:
77
+ Find a given user:
57
78
  ```ruby
58
- client = TimestampAPI::Client.find(123)
79
+ user = TimestampAPI::User.find(123)
59
80
 
60
- client.name # => "My beloved customer"
81
+ user.full_name # => "Great developer"
61
82
  ```
62
83
 
63
- Find the client of a project
84
+ #### Tasks
85
+
86
+ List tasks:
64
87
  ```ruby
65
- project = TimestampAPI::Project.find(123)
88
+ TimestampAPI::Task.all # => Returns all tasks
89
+ TimestampAPI::Task.for_project_id(123) # => Returns tasks for project 123
90
+ ```
66
91
 
67
- project.client.name # => "My beloved customer"
92
+ Find a given task:
93
+ ```ruby
94
+ task = TimestampAPI::Task.find(123)
95
+
96
+ task.name # => "My fantastic task"
97
+ task.project.name # => "My awesome project"
68
98
  ```
69
99
 
70
- ## Models
100
+ #### TimeEntry
101
+
102
+ List time entries:
103
+ ```ruby
104
+ TimestampAPI::TimeEntry.all # => Returns all time entries
105
+ TimestampAPI::TimeEntry.for_task_id(123) # => Returns time entries for task 123
106
+ ```
107
+
108
+ Find a given time entry:
109
+ ```ruby
110
+ time_entry = TimestampAPI::TimeEntry.find(123)
111
+
112
+ time_entry.comment # => "Stuff got done"
113
+ time_entry.client.name # => "My beloved customer"
114
+ time_entry.project.name # => "My awesome project"
115
+ time_entry.task.name # => "My fantastic task"
116
+ time_entry.user.full_name # => "Great developer"
117
+ ```
118
+
119
+ #### Event
120
+
121
+ List events:
122
+ ```ruby
123
+ TimestampAPI::Event.all # => Returns all events
124
+ ```
125
+
126
+ Find a given event:
127
+ ```ruby
128
+ event = TimestampAPI::Event.find(123)
129
+
130
+ event.object # => Returns the object on which event occured
131
+ ```
132
+
133
+ ## Objects representation
134
+
135
+ #### Models
71
136
 
72
137
  The objects are represented by model classes (that inherits from `TimestampAPI::Model`):
73
138
  ```ruby
@@ -77,6 +142,8 @@ project.class # => TimestampAPI::Project
77
142
  project.is_a? TimestampAPI::Model # => true
78
143
  ```
79
144
 
145
+ #### Collections
146
+
80
147
  Collections of objects are represented by `TimestampAPI::Collection` that inherits from `Array` (and implement the chainable `.where(conditions)` filter method described above). It means any `Array` method works on `TimestampAPI::Collection`:
81
148
  ```ruby
82
149
  projects = TimestampAPI::Project.all
@@ -85,6 +152,19 @@ projects.class # => TimestampAPI::Collection
85
152
  projects.map(&:name) # => ["A project", "Another project", "One more project"]
86
153
  ```
87
154
 
155
+ #### Relationships
156
+
157
+ Models can can bound together and are accessible using a simple getter:
158
+
159
+ Exemple: find the client bound to a project:
160
+ ```ruby
161
+ project = TimestampAPI::Project.find(123)
162
+
163
+ project.client.name # => "My beloved customer"
164
+ ```
165
+
166
+ :information_source: First call to such a relation getter will trigger an API request and memoize the response for network optimization.
167
+
88
168
  ## Filtering
89
169
 
90
170
  You can filter any object collection using the handy `.where()` syntax:
@@ -129,6 +209,8 @@ There's also a `bin/console` executable provided with this gem, if you want a RE
129
209
  * [x] `Client` model
130
210
  * [x] `Task` model
131
211
  * [x] `User` model (their `roles` could be enhanced, though)
212
+ * [x] `TimeEntry` model
213
+ * [x] `Event` model
132
214
  * [x] `belongs_to` relationships
133
215
 
134
216
  ### What's not implemented yet ?
@@ -136,6 +218,7 @@ There's also a `bin/console` executable provided with this gem, if you want a RE
136
218
  * [ ] _all other models_ :scream:
137
219
  * [ ] `has_many` relationships
138
220
  * [ ] document and integrate [Inch-CI](https://inch-ci.org)
221
+ * [ ] timers
139
222
 
140
223
  ## Development
141
224
 
data/lib/timestamp_api.rb CHANGED
@@ -11,10 +11,12 @@ require "timestamp_api/model_relations"
11
11
  require "timestamp_api/model_default_api_methods"
12
12
  require "timestamp_api/model"
13
13
  require "timestamp_api/collection"
14
+ require "timestamp_api/models/event"
14
15
  require "timestamp_api/models/project"
15
16
  require "timestamp_api/models/client"
16
17
  require "timestamp_api/models/task"
17
18
  require "timestamp_api/models/user"
19
+ require "timestamp_api/models/time_entry"
18
20
 
19
21
  module TimestampAPI
20
22
  extend Utils
@@ -25,9 +27,10 @@ module TimestampAPI
25
27
  attr_accessor :api_endpoint, :api_key, :verbose
26
28
  end
27
29
 
28
- def self.request(method, path, query_params = {})
29
- output(method, path, camelize_keys(query_params)) if verbose
30
- response = RestClient::Request.execute(request_options(method, path, camelize_keys(query_params)))
30
+ def self.request(method, path, query_params = {}, payload = {})
31
+ request_options = request_options(method, path, query_params, payload)
32
+ output(request_options) if verbose
33
+ response = RestClient::Request.execute(request_options)
31
34
  modelify(JSON.parse(response))
32
35
  rescue RestClient::Forbidden
33
36
  raise InvalidAPIKey
@@ -37,15 +40,16 @@ module TimestampAPI
37
40
 
38
41
  private
39
42
 
40
- def self.request_options(method, path, query_params)
43
+ def self.request_options(method, path, query_params, payload)
41
44
  {
42
45
  method: method,
43
46
  url: api_endpoint + path,
47
+ payload: camelize_keys(payload).to_json,
44
48
  headers: {
45
49
  "X-API-Key" => api_key || ENV["TIMESTAMP_API_KEY"] || raise(MissingAPIKey),
46
50
  :accept => :json,
47
51
  :user_agent => "TimestampAPI Ruby gem (https://github.com/alpinelab/timestamp_api)",
48
- :params => query_params
52
+ :params => camelize_keys(query_params)
49
53
  }
50
54
  }
51
55
  end
@@ -57,11 +61,12 @@ private
57
61
  end
58
62
  end
59
63
 
60
- def self.output(method, path, query_params)
64
+ def self.output(request_options)
61
65
  print "TimestampAPI ".colorize(:red)
62
- print "#{method.upcase} ".colorize(:yellow)
63
- full_path = path
64
- full_path += "?#{query_params.each_with_object([]) { |p, acc| acc << "#{p[0]}=#{p[1]}" }.join("&")}" unless query_params.empty?
65
- puts full_path.colorize(:yellow)
66
+ print "#{request_options[:method].upcase} ".colorize(:yellow)
67
+ full_path = request_options[:url]
68
+ full_path += "?#{request_options[:headers][:params].each_with_object([]) { |p, acc| acc << "#{p[0]}=#{p[1]}" }.join("&")}" unless request_options[:headers][:params].empty?
69
+ print full_path.colorize(:yellow)
70
+ puts " #{request_options[:payload] unless request_options[:payload].empty?}".colorize(:green)
66
71
  end
67
72
  end
@@ -25,7 +25,7 @@ module TimestampAPI
25
25
 
26
26
  def validate_init_data!
27
27
  class_basename = self.class.name.split("::").last
28
- raise InvalidModelData.new(class_basename, json_data) unless json_data.is_a?(Hash) && json_data["object"] == class_basename.downcase
28
+ raise InvalidModelData.new(class_basename, json_data) unless json_data.is_a?(Hash) && json_data["object"] == camelize(class_basename)
29
29
  end
30
30
  end
31
31
  end
@@ -1,5 +1,7 @@
1
1
  module TimestampAPI
2
2
  class ModelRegistry
3
+ extend Utils
4
+
3
5
  class << self
4
6
 
5
7
  @@registry = {}
@@ -20,7 +22,7 @@ module TimestampAPI
20
22
  private
21
23
 
22
24
  def registry_key(klass)
23
- klass.name.split("::").last.gsub(/(.)([A-Z])/, '\1_\2').downcase
25
+ camelize(klass.name.split("::").last)
24
26
  end
25
27
  end
26
28
  end
@@ -0,0 +1,11 @@
1
+ module TimestampAPI
2
+ class Event < Model
3
+ api_path "/events"
4
+
5
+ has_attributes :resource_object, :change_type, :data
6
+
7
+ def object
8
+ TimestampAPI::ModelRegistry.model_for(data).new(data)
9
+ end
10
+ end
11
+ end
@@ -6,5 +6,15 @@ module TimestampAPI
6
6
  :target_completion_date, :is_archived, :is_billable, :is_public, :is_approvable
7
7
 
8
8
  belongs_to :client
9
+
10
+ def enter_time(task_id, day, duration_in_minutes, comment = "")
11
+ TimestampAPI.request(:post, "#{@@api_path}/#{id}/enterTime", {}, {
12
+ task_id: task_id,
13
+ day: day.strftime("%FT%T%:z"),
14
+ time_value: duration_in_minutes,
15
+ time_unit: "Minutes",
16
+ comment: comment
17
+ }).object
18
+ end
9
19
  end
10
20
  end
@@ -0,0 +1,16 @@
1
+ module TimestampAPI
2
+ class TimeEntry < Model
3
+ api_path "/timeEntries"
4
+
5
+ has_attributes :id, :created_at, :comment, :day, :minutes, :is_archived, :is_approved, :is_invoiced, :is_externally_owned, :is_locked
6
+
7
+ belongs_to :client
8
+ belongs_to :project
9
+ belongs_to :task
10
+ belongs_to :user
11
+
12
+ def self.for_task_id(task_id)
13
+ all("$filter" => "TaskId%20eq%20#{task_id}")
14
+ end
15
+ end
16
+ end
@@ -4,5 +4,9 @@ module TimestampAPI
4
4
 
5
5
  has_attributes :id, :created_at, :user_type, :first_name, :last_name, :email_address, :time_zone, :culture, :is_active,
6
6
  :avatar_url, :last_accessed, :invited_at, :roles, :employment_type, :time_entry_mode, :importStatus, :invited
7
+
8
+ def full_name
9
+ "#{first_name} #{last_name}"
10
+ end
7
11
  end
8
12
  end
@@ -1,3 +1,3 @@
1
1
  module TimestampAPI
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timestamp_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Baudino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-31 00:00:00.000000000 Z
11
+ date: 2016-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -165,8 +165,10 @@ files:
165
165
  - lib/timestamp_api/model_registry.rb
166
166
  - lib/timestamp_api/model_relations.rb
167
167
  - lib/timestamp_api/models/client.rb
168
+ - lib/timestamp_api/models/event.rb
168
169
  - lib/timestamp_api/models/project.rb
169
170
  - lib/timestamp_api/models/task.rb
171
+ - lib/timestamp_api/models/time_entry.rb
170
172
  - lib/timestamp_api/models/user.rb
171
173
  - lib/timestamp_api/utils.rb
172
174
  - lib/timestamp_api/version.rb