dovico 1.1.0 → 1.2.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/CHANGELOG.md +7 -0
- data/README.md +68 -16
- data/dovico-client.gemspec +1 -0
- data/lib/dovico/api_client.rb +9 -1
- data/lib/dovico/app.rb +23 -1
- data/lib/dovico/config_parser.rb +3 -2
- data/lib/dovico/model/assignment.rb +1 -1
- data/lib/dovico/model/employee.rb +1 -1
- data/lib/dovico/model/project.rb +10 -6
- data/lib/dovico/model/time_entry.rb +6 -2
- data/lib/dovico/version.rb +1 -1
- data/spec/unit/dovico/api_client_spec.rb +10 -0
- data/spec/unit/dovico/model/project_spec.rb +18 -6
- data/spec/unit/dovico/model/time_entry_spec.rb +12 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 641eaa573848e60b70368be58db24872e2237a24
|
4
|
+
data.tar.gz: ca2e3477d9d1a70545e95d223aed5101796aec50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b837afe730bbc5fe4a057c2b71ba8910a73cb50d0de4cc5dd9a738d0eecc79d19c7c108709f9d6f2bf4559e22cf93ba223e8d6af0fb6fc7a84a6cc2acd0a3b3
|
7
|
+
data.tar.gz: 8a7550467aaafa92c599e1f9aa556a534ca15cdb35c0a095523cb4f5e50b97bf8e2755648cefae7590f8f44688a10bc9782ba5fdf40d31f880489dd7d0337a52
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
# Next version
|
2
|
+
- Your contribution!
|
3
|
+
|
4
|
+
# Version 1.2.0
|
5
|
+
- Update [README.md](README.md)
|
6
|
+
- Add `--clear` option to delete time entries
|
7
|
+
- Fix a typo on Projet URL
|
8
|
+
- Fix formatting tasks list when mutliple tasks are associated to an assignment
|
2
9
|
|
3
10
|
# Version 1.1.0
|
4
11
|
- Remove `bin/console` from the Gem
|
data/README.md
CHANGED
@@ -2,9 +2,16 @@
|
|
2
2
|
|
3
3
|
Repository for Dovico API management.
|
4
4
|
|
5
|
+
# Requirements
|
6
|
+
- Ruby 2.2.2 or newer
|
7
|
+
|
5
8
|
# Installation
|
9
|
+
`gem install dovico`
|
10
|
+
|
11
|
+
# Configuration
|
12
|
+
|
6
13
|
## Dovico authentication
|
7
|
-
Dovico provide a way to generate a 3rd party token. This token
|
14
|
+
Dovico provide a way to generate a 3rd party token. This token provides a full access to your account:
|
8
15
|
- Do not expose your token.
|
9
16
|
- If you believe your token has been exposed publicly, regenerate a new one. The previous token will be invalidated.
|
10
17
|
|
@@ -22,15 +29,11 @@ user_token: "<token you have copied from dovico.net page>"
|
|
22
29
|
client_token: "<token given by your company's dovico admin>"
|
23
30
|
~~~
|
24
31
|
|
25
|
-
## Install required libraries
|
26
|
-
* Install Ruby 2.4.0
|
27
|
-
* `make install`
|
28
|
-
|
29
32
|
## Setup your default timesheet
|
30
|
-
* List the available tasks with `
|
33
|
+
* List the available tasks with `dovico --tasks`
|
31
34
|
|
32
35
|
~~~
|
33
|
-
$
|
36
|
+
$ dovico --tasks
|
34
37
|
== List of available projects ==
|
35
38
|
Project | Task | Description
|
36
39
|
1200 | 100 | Sauron Project: Forge the One Ring
|
@@ -74,30 +77,79 @@ assignments:
|
|
74
77
|
|
75
78
|
# Usage
|
76
79
|
## Display informations on your account
|
77
|
-
`
|
80
|
+
`dovico --myself`
|
81
|
+
|
82
|
+
~~~
|
83
|
+
$ dovico --myself
|
84
|
+
Informations about yourself
|
85
|
+
- ID: 42
|
86
|
+
- First Name: Gandalf
|
87
|
+
- Last Name: The White
|
88
|
+
~~~
|
78
89
|
|
79
90
|
## Display the list of the tasks
|
80
|
-
`
|
91
|
+
`dovico --tasks`
|
92
|
+
~~~
|
93
|
+
$ dovico --tasks
|
94
|
+
== List of available projects ==
|
95
|
+
Project | Task | Description
|
96
|
+
1200 | 100 | Sauron Project: Forge the One Ring
|
97
|
+
1200 | 110 | Sauron Project: Attack Gondor
|
98
|
+
1400 | 100 | Gandalf Project: Meet Bilbo
|
99
|
+
1400 | 120 | Gandalf Project: Convince Frodo
|
100
|
+
1600 | 100 | Frodo Project: Go home
|
101
|
+
~~~
|
81
102
|
|
82
103
|
## Fill the timesheet
|
104
|
+
`dovico --fill [date options]`
|
105
|
+
|
106
|
+
The date options are detailed below. All the other commands use the same format for these date options.
|
107
|
+
|
83
108
|
### For the current week
|
84
|
-
`
|
109
|
+
`dovico --fill --current_week`
|
85
110
|
|
86
111
|
### For today
|
87
|
-
`
|
112
|
+
`dovico --fill --today`
|
88
113
|
|
89
114
|
### For a specific [commercial week](http://www.epochconverter.com/weeks/)
|
90
|
-
`
|
115
|
+
`dovicon --fill --week=49`
|
91
116
|
|
92
117
|
Year can be set too:
|
93
|
-
`
|
118
|
+
`dovico --fill --year=2015 --week=40`
|
94
119
|
|
95
120
|
### For a specific day
|
96
|
-
`
|
121
|
+
`dovico --fill --day=2017-12-31`
|
97
122
|
|
98
|
-
|
99
|
-
|
123
|
+
## Show the timesheet
|
124
|
+
`dovico --show [date options]`
|
125
|
+
|
126
|
+
~~~
|
127
|
+
$ dovico --show --start=2017-01-02 --end=2017-01-12
|
128
|
+
== List of Time Entries between 2017-01-02 and 2017-01-06 ==
|
129
|
+
2017-01-02 [××××××××××××××] : [not_submitted] 7h Sauron Project: Forge the One Ring
|
130
|
+
2017-01-03 [××××××××××××××] : [not_submitted] 7h Sauron Project: Attack Gondor
|
131
|
+
2017-01-12 [××××] : [under_review] 2h Gandalf Project: Meet Bilbo
|
132
|
+
2017-01-12 [××××××××] : [under_review] 4h Gandalf Project: Convince Frodo
|
133
|
+
2017-01-12 [××] : [under_review] 1h Frodo Project: Go home
|
134
|
+
~~~
|
135
|
+
|
136
|
+
## Submit the timesheet
|
137
|
+
`dovico --submit [date options]`
|
138
|
+
|
139
|
+
Once submitted, the timesheet can't be edited.
|
140
|
+
|
141
|
+
## Delete timesheet
|
142
|
+
`dovico --clear [date options]`
|
143
|
+
|
144
|
+
A confirmation will be asked before the deletion.
|
145
|
+
~~~
|
146
|
+
$ dovico --clear --day=2017-01-05
|
147
|
+
• 1 Time Entries to be deleted. Are you sure? (yes/no)
|
148
|
+
yes
|
149
|
+
✓ 1 Time Entries deleted
|
150
|
+
~~~
|
100
151
|
|
152
|
+
# Contributing
|
101
153
|
You are warmly welcome to contribute to the project!
|
102
154
|
|
103
155
|
# Dovico API Documentation
|
data/dovico-client.gemspec
CHANGED
data/lib/dovico/api_client.rb
CHANGED
@@ -24,6 +24,10 @@ module Dovico
|
|
24
24
|
perform!(:put, path, params: params, body: body)
|
25
25
|
end
|
26
26
|
|
27
|
+
def delete(path, params: {}, body: nil)
|
28
|
+
perform!(:delete, path, params: params, body: body)
|
29
|
+
end
|
30
|
+
|
27
31
|
private
|
28
32
|
|
29
33
|
attr_accessor :client_token, :user_token
|
@@ -60,7 +64,11 @@ module Dovico
|
|
60
64
|
raise "Error during HTTP request"
|
61
65
|
end
|
62
66
|
|
63
|
-
|
67
|
+
if response.body.length > 0
|
68
|
+
JSON.parse(response.body)
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
64
72
|
end
|
65
73
|
end
|
66
74
|
end
|
data/lib/dovico/app.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'easy_app_helper'
|
2
|
+
require 'highline'
|
2
3
|
|
3
4
|
module Dovico
|
4
5
|
class App
|
@@ -37,7 +38,10 @@ EOL
|
|
37
38
|
config.add_command_line_section('Submit the timesheets') do |slop|
|
38
39
|
slop.on :submit, 'Submit timesheets', argument: false
|
39
40
|
end
|
40
|
-
config.add_command_line_section('
|
41
|
+
config.add_command_line_section('Clear the timesheets') do |slop|
|
42
|
+
slop.on :clear, 'Clear the timesheets', argument: false
|
43
|
+
end
|
44
|
+
config.add_command_line_section('Date options (required for --show, --fill, --submit and --clear)') do |slop|
|
41
45
|
slop.on :current_week, 'Current week', argument: false
|
42
46
|
slop.on :today, 'Current day', argument: false
|
43
47
|
slop.on :day, 'Specific day', argument: true
|
@@ -65,6 +69,10 @@ EOL
|
|
65
69
|
display_tasks
|
66
70
|
end
|
67
71
|
|
72
|
+
if config[:clear]
|
73
|
+
clear_time_entries(start_date, end_date)
|
74
|
+
end
|
75
|
+
|
68
76
|
if config[:show]
|
69
77
|
display_time_entries(start_date, end_date)
|
70
78
|
end
|
@@ -112,8 +120,22 @@ EOL
|
|
112
120
|
puts ""
|
113
121
|
end
|
114
122
|
|
123
|
+
def clear_time_entries(start_date, end_date)
|
124
|
+
time_entries = TimeEntry.search(start_date, end_date)
|
125
|
+
if highline.agree("• #{time_entries.count} Time Entries to be deleted. Are you sure? (yes/no)")
|
126
|
+
time_entries.each do |time_entry|
|
127
|
+
time_entry.delete!
|
128
|
+
end
|
129
|
+
puts "✓ #{time_entries.count} Time Entries deleted"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
115
133
|
def display_help
|
116
134
|
puts config.command_line_help
|
117
135
|
end
|
136
|
+
|
137
|
+
def highline
|
138
|
+
@highline ||= HighLine.new
|
139
|
+
end
|
118
140
|
end
|
119
141
|
end
|
data/lib/dovico/config_parser.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Dovico
|
2
2
|
class ConfigParser
|
3
|
-
AVAILABLE_ACTIONS = [:myself, :tasks, :show, :fill, :submit]
|
3
|
+
AVAILABLE_ACTIONS = [:myself, :tasks, :show, :fill, :submit, :clear]
|
4
|
+
DATE_REQUIRED_ACTIONS = [:show, :fill, :submit, :clear]
|
4
5
|
|
5
6
|
def initialize(config)
|
6
7
|
@config = config
|
@@ -12,7 +13,7 @@ module Dovico
|
|
12
13
|
true
|
13
14
|
elsif AVAILABLE_ACTIONS.map{|action| config[action] }.compact.empty?
|
14
15
|
true
|
15
|
-
elsif (
|
16
|
+
elsif !(@start_date && @end_date) && !DATE_REQUIRED_ACTIONS.map{|action| config[action] }.compact.empty?
|
16
17
|
true
|
17
18
|
else
|
18
19
|
false
|
data/lib/dovico/model/project.rb
CHANGED
@@ -16,15 +16,19 @@ module Dovico
|
|
16
16
|
projects = projects_search["Assignments"].map {|project_hash| parse(project_hash) }
|
17
17
|
|
18
18
|
projects.each do |project|
|
19
|
-
tasks_search = ApiClient.get("#{URL_PATH}
|
20
|
-
|
19
|
+
tasks_search = ApiClient.get("#{URL_PATH}/#{project.assignement_id}")
|
20
|
+
tasks = tasks_search["Assignments"].map {|task_hash| Task.parse(task_hash) }
|
21
|
+
|
22
|
+
project.tasks = tasks.sort_by do |task|
|
23
|
+
task.id
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
23
27
|
projects
|
24
28
|
end
|
25
29
|
|
26
30
|
def self.format_all
|
27
|
-
text = " Project | Task | Description"
|
31
|
+
text = " Project | Task | Description\n"
|
28
32
|
text += all.map(&:to_s).join("\n")
|
29
33
|
end
|
30
34
|
|
@@ -32,9 +36,9 @@ module Dovico
|
|
32
36
|
text = ''
|
33
37
|
|
34
38
|
if tasks.count > 0
|
35
|
-
tasks.
|
36
|
-
|
37
|
-
end
|
39
|
+
text += tasks.map do |task|
|
40
|
+
sprintf " %7d | %4d | %s: %s", id, task.id, name, task.name
|
41
|
+
end.join("\n")
|
38
42
|
else
|
39
43
|
text += sprintf " %7d | | %s (No tasks linked)", id, name
|
40
44
|
end
|
@@ -2,7 +2,7 @@ require 'active_attr'
|
|
2
2
|
|
3
3
|
module Dovico
|
4
4
|
class TimeEntry
|
5
|
-
URL_PATH = 'TimeEntries
|
5
|
+
URL_PATH = 'TimeEntries'
|
6
6
|
|
7
7
|
include ActiveAttr::Model
|
8
8
|
|
@@ -41,7 +41,7 @@ module Dovico
|
|
41
41
|
|
42
42
|
def self.search(start_date, end_date)
|
43
43
|
api_response = ApiClient.get(
|
44
|
-
|
44
|
+
URL_PATH,
|
45
45
|
params: {
|
46
46
|
daterange: "#{start_date} #{end_date}"
|
47
47
|
},
|
@@ -75,6 +75,10 @@ module Dovico
|
|
75
75
|
ApiClient.put(URL_PATH, body: [to_api].to_json)
|
76
76
|
end
|
77
77
|
|
78
|
+
def delete!
|
79
|
+
ApiClient.delete("#{URL_PATH}/#{id}")
|
80
|
+
end
|
81
|
+
|
78
82
|
def to_api
|
79
83
|
{
|
80
84
|
"ID": id,
|
data/lib/dovico/version.rb
CHANGED
@@ -77,5 +77,15 @@ module Dovico
|
|
77
77
|
expect(response).to eq({"Stubbed": "Response"}.stringify_keys)
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
describe ".delete" do
|
82
|
+
it 'perform a DELETE request' do
|
83
|
+
stub_request(:delete, "#{Dovico::ApiClient::API_URL}TimeEntries/42?version=#{Dovico::ApiClient::API_VERSION}")
|
84
|
+
.to_return(body: '')
|
85
|
+
|
86
|
+
response = Dovico::ApiClient.delete('TimeEntries/42')
|
87
|
+
expect(response).to eq(nil)
|
88
|
+
end
|
89
|
+
end
|
80
90
|
end
|
81
91
|
end
|
@@ -20,7 +20,14 @@ module Dovico
|
|
20
20
|
"Assignments": [project_api_hash]
|
21
21
|
}.stringify_keys
|
22
22
|
end
|
23
|
-
let(:
|
23
|
+
let(:task_api_hash_1) do
|
24
|
+
{
|
25
|
+
"ItemID": "995",
|
26
|
+
"AssignmentID": "E456",
|
27
|
+
"Name": "Task write specs, second part",
|
28
|
+
}.stringify_keys
|
29
|
+
end
|
30
|
+
let(:task_api_hash_2) do
|
24
31
|
{
|
25
32
|
"ItemID": "789",
|
26
33
|
"AssignmentID": "E456",
|
@@ -31,14 +38,14 @@ module Dovico
|
|
31
38
|
end
|
32
39
|
let(:tasks_api_hash) do
|
33
40
|
{
|
34
|
-
"Assignments": [
|
41
|
+
"Assignments": [task_api_hash_1, task_api_hash_2]
|
35
42
|
}.stringify_keys
|
36
43
|
end
|
37
44
|
|
38
45
|
describe ".all" do
|
39
46
|
before do
|
40
47
|
allow(ApiClient).to receive(:get).with(Dovico::Project::URL_PATH).and_return(projects_api_hash)
|
41
|
-
allow(ApiClient).to receive(:get).with("#{Dovico::Project::URL_PATH}T456").and_return(tasks_api_hash)
|
48
|
+
allow(ApiClient).to receive(:get).with("#{Dovico::Project::URL_PATH}/T456").and_return(tasks_api_hash)
|
42
49
|
end
|
43
50
|
|
44
51
|
it "lists all the assignements" do
|
@@ -50,7 +57,7 @@ module Dovico
|
|
50
57
|
expect(project.id).to eq('123')
|
51
58
|
expect(project.name).to eq('Project Dovico API Client')
|
52
59
|
|
53
|
-
expect(project.tasks.count).to eq(
|
60
|
+
expect(project.tasks.count).to eq(2)
|
54
61
|
task = project.tasks.first
|
55
62
|
expect(task.id).to eq('789')
|
56
63
|
expect(task.name).to eq('Task write specs')
|
@@ -60,11 +67,16 @@ module Dovico
|
|
60
67
|
describe ".format_all" do
|
61
68
|
before do
|
62
69
|
allow(ApiClient).to receive(:get).with(Dovico::Project::URL_PATH).and_return(projects_api_hash)
|
63
|
-
allow(ApiClient).to receive(:get).with("#{Dovico::Project::URL_PATH}T456").and_return(tasks_api_hash)
|
70
|
+
allow(ApiClient).to receive(:get).with("#{Dovico::Project::URL_PATH}/T456").and_return(tasks_api_hash)
|
64
71
|
end
|
65
72
|
|
66
73
|
it 'returns projects with formatted text' do
|
67
|
-
|
74
|
+
expected_strings = [
|
75
|
+
' Project | Task | Description',
|
76
|
+
' 123 | 789 | Project Dovico API Client: Task write specs',
|
77
|
+
' 123 | 995 | Project Dovico API Client: Task write specs, second part',
|
78
|
+
]
|
79
|
+
expect(Dovico::Project.format_all).to eq(expected_strings.join("\n"))
|
68
80
|
end
|
69
81
|
end
|
70
82
|
|
@@ -182,6 +182,18 @@ module Dovico
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
|
+
describe ".delete!" do
|
186
|
+
before do
|
187
|
+
allow(ApiClient).to receive(:delete)
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'calls the API and delete TimeEntries objects' do
|
191
|
+
subject.delete!
|
192
|
+
|
193
|
+
expect(ApiClient).to have_received(:delete).with("#{Dovico::TimeEntry::URL_PATH}/#{subject.id}")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
185
197
|
describe ".to_api" do
|
186
198
|
it 'serializes the object' do
|
187
199
|
expect(subject.to_api).to eq(
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dovico
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Théophile Helleboid
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-10-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: easy_app_helper
|
@@ -53,6 +53,20 @@ dependencies:
|
|
53
53
|
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: highline
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
56
70
|
- !ruby/object:Gem::Dependency
|
57
71
|
name: pry
|
58
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -332,7 +346,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
332
346
|
version: '0'
|
333
347
|
requirements: []
|
334
348
|
rubyforge_project:
|
335
|
-
rubygems_version: 2.6.
|
349
|
+
rubygems_version: 2.6.13
|
336
350
|
signing_key:
|
337
351
|
specification_version: 4
|
338
352
|
summary: Simple client & tools for http://www.dovico.com/.
|