xoggl 1.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.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +52 -0
- data/README.md +22 -0
- data/Rakefile +9 -0
- data/bin/xoggl +29 -0
- data/lib/xoggl/client.rb +94 -0
- data/lib/xoggl/version.rb +3 -0
- data/lib/xoggl.rb +4 -0
- data/spec/lib/xoggl/client_spec.rb +85 -0
- data/spec/spec_helper.rb +12 -0
- data/xoggl.gemspec +31 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b7b3485f9eb4edb7339c734264e8d3009a13fb64
|
4
|
+
data.tar.gz: 9de67a70b3ffb000e93e4f15b47f1af786173269
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ea869a02f8271bd857e9ef129160209bd77660752b7f45cebce7ebed8ad941a64998c2c72ed2c61fe9aac06255ed86916015c713dfc6e06cb7c0baf9b3ace9cf
|
7
|
+
data.tar.gz: d9e467955c1eb680c2aaef63de7f491cd566bc5973ba0d58eeb74a21676439d3e7682f38f95ce64b2fa620d8ee86c6757d73fb385c90695bb47341d863ca1fe9
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
xoggl (1.0.0)
|
5
|
+
awesome_print
|
6
|
+
gli
|
7
|
+
holidays
|
8
|
+
togglv8
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
awesome_print (1.8.0)
|
14
|
+
diff-lcs (1.3)
|
15
|
+
faraday (0.13.1)
|
16
|
+
multipart-post (>= 1.2, < 3)
|
17
|
+
gli (2.16.1)
|
18
|
+
holidays (6.1.0)
|
19
|
+
logger (1.2.8)
|
20
|
+
multipart-post (2.0.0)
|
21
|
+
oj (3.3.5)
|
22
|
+
rake (12.0.0)
|
23
|
+
rspec (3.6.0)
|
24
|
+
rspec-core (~> 3.6.0)
|
25
|
+
rspec-expectations (~> 3.6.0)
|
26
|
+
rspec-mocks (~> 3.6.0)
|
27
|
+
rspec-core (3.6.0)
|
28
|
+
rspec-support (~> 3.6.0)
|
29
|
+
rspec-expectations (3.6.0)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.6.0)
|
32
|
+
rspec-mocks (3.6.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.6.0)
|
35
|
+
rspec-support (3.6.0)
|
36
|
+
togglv8 (1.2.1)
|
37
|
+
faraday
|
38
|
+
logger
|
39
|
+
oj
|
40
|
+
|
41
|
+
PLATFORMS
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
bundler
|
46
|
+
rake
|
47
|
+
rspec
|
48
|
+
rspec-mocks
|
49
|
+
xoggl!
|
50
|
+
|
51
|
+
BUNDLED WITH
|
52
|
+
1.15.4
|
data/README.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Xoggl
|
2
|
+
|
3
|
+
Simple Toggl command line client
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
`gem install xoggl`
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
Create a `~/.toggl` file containing your API token (found in your [Toggl profile](https://toggl.com/app/profile))
|
10
|
+
|
11
|
+
### Insert vacation days entries
|
12
|
+
`xoggl vacation 2016-01-01 2016-01-15`
|
13
|
+
|
14
|
+
### Insert work days entries
|
15
|
+
`xoggl work [project_name] 2016-01-01 2016-01-15`
|
16
|
+
|
17
|
+
## Development
|
18
|
+
Install dependencies
|
19
|
+
`bundle install`
|
20
|
+
|
21
|
+
Run tests
|
22
|
+
`rake spec`
|
data/Rakefile
ADDED
data/bin/xoggl
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'gli'
|
5
|
+
require 'xoggl'
|
6
|
+
|
7
|
+
include GLI::App
|
8
|
+
|
9
|
+
program_desc 'A simple Toggl cli'
|
10
|
+
|
11
|
+
pre do
|
12
|
+
@xoggl = Xoggl::Client.new
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'track days entries for a project'
|
16
|
+
command :work do |c|
|
17
|
+
c.action do |_, _, args|
|
18
|
+
@xoggl.log_work(args[1], args[2], args[0])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'track days entries for vacation'
|
23
|
+
command :vacation do |c|
|
24
|
+
c.action do |_, _, args|
|
25
|
+
@xoggl.log_vacation(args[0], args[1])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
exit run(ARGV)
|
data/lib/xoggl/client.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'togglv8'
|
2
|
+
require 'holidays'
|
3
|
+
|
4
|
+
module Xoggl
|
5
|
+
class Client
|
6
|
+
def initialize(toggl = TogglV8::API.new)
|
7
|
+
@toggl = toggl
|
8
|
+
@zone_offset = Time.now.utc_offset / 3600
|
9
|
+
end
|
10
|
+
|
11
|
+
def log_work(start_isodate, end_isodate, project_name)
|
12
|
+
do_between(start_isodate, end_isodate) do |date|
|
13
|
+
log_work_day(date, project_name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def log_vacation(start_isodate, end_isodate)
|
18
|
+
do_between(start_isodate, end_isodate) do |date|
|
19
|
+
log_vacation_day(date) unless to_skip?(date)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def do_between(start_isodate, end_isodate)
|
26
|
+
date = DateTime.iso8601(start_isodate)
|
27
|
+
end_date = DateTime.iso8601(end_isodate)
|
28
|
+
|
29
|
+
raise ArgumentError.new('End date must be greater than or equal to start date') if end_date < date
|
30
|
+
|
31
|
+
while date <= end_date
|
32
|
+
yield(date)
|
33
|
+
|
34
|
+
date = date.next_day
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_skip?(date)
|
39
|
+
date.saturday? || date.sunday? || Holidays.on(date, :it, :observed).any?
|
40
|
+
end
|
41
|
+
|
42
|
+
def log_work_day(date, project_name)
|
43
|
+
create_work_entry(date_time_from(date, 9), project_name)
|
44
|
+
create_work_entry(date_time_from(date, 14), project_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def log_vacation_day(date)
|
48
|
+
create_vacation_entry(date_time_from(date, 9))
|
49
|
+
create_vacation_entry(date_time_from(date, 14))
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_work_entry(start_time, project_name)
|
53
|
+
@toggl.create_time_entry(
|
54
|
+
'billable' => true,
|
55
|
+
'description' => project_name,
|
56
|
+
'tags' => [],
|
57
|
+
'pid' => project_id_from(project_name),
|
58
|
+
'duration' => 14_400,
|
59
|
+
'start' => @toggl.iso8601(start_time)
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_vacation_entry(start_time)
|
64
|
+
@toggl.create_time_entry(
|
65
|
+
'billable' => false,
|
66
|
+
'description' => 'Ferie',
|
67
|
+
'tags' => ['Ferie'],
|
68
|
+
'pid' => vacation_project_id,
|
69
|
+
'duration' => 14_400,
|
70
|
+
'start' => @toggl.iso8601(start_time)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def date_time_from(date, hours)
|
75
|
+
DateTime.new(date.year, date.month, date.day, hours - @zone_offset)
|
76
|
+
end
|
77
|
+
|
78
|
+
def workspace_id
|
79
|
+
@workspace_id ||= @toggl.my_workspaces.first['id']
|
80
|
+
end
|
81
|
+
|
82
|
+
def vacation_project_id
|
83
|
+
@vacation_project_id ||= @toggl.my_projects.select do |project|
|
84
|
+
project['name'] == 'Assenza'
|
85
|
+
end.first['id']
|
86
|
+
end
|
87
|
+
|
88
|
+
def project_id_from(project_name)
|
89
|
+
@toggl.my_projects.select do |project|
|
90
|
+
project['name'] == project_name
|
91
|
+
end.first['id']
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/xoggl.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
describe Xoggl::Client do
|
2
|
+
before :all do
|
3
|
+
@toggl = TogglV8::API.new('9b07c50c5126baf8c2d263b3dbfde3ee')
|
4
|
+
@client = Xoggl::Client.new(@toggl)
|
5
|
+
@workspace_id = @toggl.workspaces.first['id']
|
6
|
+
|
7
|
+
@toggl.create_project('name' => 'Assenza', 'wid' => @workspace_id)
|
8
|
+
@toggl.create_project('name' => 'A project', 'wid' => @workspace_id)
|
9
|
+
end
|
10
|
+
|
11
|
+
after :all do
|
12
|
+
delete_all_projects(@toggl, @workspace_id)
|
13
|
+
projects = @toggl.my_projects
|
14
|
+
expect(projects).to be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
after :each do
|
18
|
+
entries.each do |entry|
|
19
|
+
@toggl.delete_time_entry(entry['id'])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'vacation' do
|
24
|
+
it 'creates the entry' do
|
25
|
+
start_date = '2016-01-04'
|
26
|
+
end_date = '2016-01-04'
|
27
|
+
|
28
|
+
@client.log_vacation(start_date, end_date)
|
29
|
+
|
30
|
+
expect(entries.count).to eq(2)
|
31
|
+
expect(entries.first).to include('description' => 'Ferie')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'does not create the entry on weekends' do
|
35
|
+
start_date = '2016-01-09'
|
36
|
+
end_date = '2016-01-09'
|
37
|
+
|
38
|
+
@client.log_vacation(start_date, end_date)
|
39
|
+
|
40
|
+
expect(entries).to be_empty
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'does not create the entry on holidays' do
|
44
|
+
start_date = '2016-01-06'
|
45
|
+
end_date = '2016-01-06'
|
46
|
+
|
47
|
+
@client.log_vacation(start_date, end_date)
|
48
|
+
|
49
|
+
expect(entries).to be_empty
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'work' do
|
54
|
+
it 'does not create an entry with a start date greater than end date' do
|
55
|
+
start_date = '2016-10-05'
|
56
|
+
end_date = '2016-10-04'
|
57
|
+
|
58
|
+
expect do
|
59
|
+
@client.log_work(start_date, end_date, 'A project')
|
60
|
+
end.to raise_error(ArgumentError)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'creates an entry' do
|
64
|
+
start_date = '2016-01-04'
|
65
|
+
end_date = '2016-01-04'
|
66
|
+
|
67
|
+
@client.log_work(start_date, end_date, 'A project')
|
68
|
+
|
69
|
+
expect(entries.count).to eq(2)
|
70
|
+
expect(entries.first).to include('description' => 'A project')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def entries
|
75
|
+
@toggl.get_time_entries(start_date: '2016-01-01', end_date: '2016-01-09')
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete_all_projects(toggl, workspace_id)
|
79
|
+
projects = toggl.projects(workspace_id)
|
80
|
+
project_ids = projects.map { |p| p['id'] }
|
81
|
+
return if project_ids.empty?
|
82
|
+
|
83
|
+
toggl.delete_projects(project_ids)
|
84
|
+
end
|
85
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'xoggl'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.expect_with :rspec do |expectations|
|
5
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
6
|
+
end
|
7
|
+
|
8
|
+
config.mock_with :rspec do |mocks|
|
9
|
+
mocks.verify_partial_doubles = true
|
10
|
+
end
|
11
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
12
|
+
end
|
data/xoggl.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'xoggl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'xoggl'
|
8
|
+
spec.version = Xoggl::VERSION
|
9
|
+
spec.authors = ['Filippo Liverani']
|
10
|
+
spec.email = ['filippo.liverani@xpeppers.com']
|
11
|
+
spec.summary = 'Simple Toggl cli'
|
12
|
+
spec.homepage = 'https://github.com/xpeppers/xoggl'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split("\n") - ['.gitignore', '.travis.yml']
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.requirements << 'A Toggl account (https://toggl.com/)'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rspec'
|
25
|
+
spec.add_development_dependency 'rspec-mocks'
|
26
|
+
|
27
|
+
spec.add_dependency 'togglv8'
|
28
|
+
spec.add_dependency 'awesome_print'
|
29
|
+
spec.add_dependency 'holidays'
|
30
|
+
spec.add_dependency 'gli'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xoggl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Filippo Liverani
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-mocks
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: togglv8
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: awesome_print
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: holidays
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: gli
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- filippo.liverani@xpeppers.com
|
128
|
+
executables:
|
129
|
+
- xoggl
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".rspec"
|
134
|
+
- Gemfile
|
135
|
+
- Gemfile.lock
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- bin/xoggl
|
139
|
+
- lib/xoggl.rb
|
140
|
+
- lib/xoggl/client.rb
|
141
|
+
- lib/xoggl/version.rb
|
142
|
+
- spec/lib/xoggl/client_spec.rb
|
143
|
+
- spec/spec_helper.rb
|
144
|
+
- xoggl.gemspec
|
145
|
+
homepage: https://github.com/xpeppers/xoggl
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata: {}
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
requirements:
|
164
|
+
- A Toggl account (https://toggl.com/)
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 2.6.12
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: Simple Toggl cli
|
170
|
+
test_files:
|
171
|
+
- spec/lib/xoggl/client_spec.rb
|
172
|
+
- spec/spec_helper.rb
|