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 +4 -4
- data/README.md +98 -15
- data/lib/timestamp_api.rb +15 -10
- data/lib/timestamp_api/model.rb +1 -1
- data/lib/timestamp_api/model_registry.rb +3 -1
- data/lib/timestamp_api/models/event.rb +11 -0
- data/lib/timestamp_api/models/project.rb +10 -0
- data/lib/timestamp_api/models/time_entry.rb +16 -0
- data/lib/timestamp_api/models/user.rb +4 -0
- data/lib/timestamp_api/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67c11519366433b792e43a3d44a6a2dae38e6b2a
|
4
|
+
data.tar.gz: 72c994d54a419b40ba8bc14bb7459edba86b18e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
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
|
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
|
-
####
|
70
|
+
#### Users
|
50
71
|
|
51
|
-
List
|
72
|
+
List users:
|
52
73
|
```ruby
|
53
|
-
TimestampAPI::
|
74
|
+
TimestampAPI::User.all # => Returns all users
|
54
75
|
```
|
55
76
|
|
56
|
-
Find a given
|
77
|
+
Find a given user:
|
57
78
|
```ruby
|
58
|
-
|
79
|
+
user = TimestampAPI::User.find(123)
|
59
80
|
|
60
|
-
|
81
|
+
user.full_name # => "Great developer"
|
61
82
|
```
|
62
83
|
|
63
|
-
|
84
|
+
#### Tasks
|
85
|
+
|
86
|
+
List tasks:
|
64
87
|
```ruby
|
65
|
-
|
88
|
+
TimestampAPI::Task.all # => Returns all tasks
|
89
|
+
TimestampAPI::Task.for_project_id(123) # => Returns tasks for project 123
|
90
|
+
```
|
66
91
|
|
67
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
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(
|
64
|
+
def self.output(request_options)
|
61
65
|
print "TimestampAPI ".colorize(:red)
|
62
|
-
print "#{method.upcase} ".colorize(:yellow)
|
63
|
-
full_path =
|
64
|
-
full_path += "?#{
|
65
|
-
|
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
|
data/lib/timestamp_api/model.rb
CHANGED
@@ -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
|
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
|
25
|
+
camelize(klass.name.split("::").last)
|
24
26
|
end
|
25
27
|
end
|
26
28
|
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
|
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.
|
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
|
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
|