gitloggl 0.1.1 → 0.2
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/Gemfile.lock +4 -1
- data/bin/console +6 -0
- data/gitloggl.gemspec +1 -0
- data/lib/gitloggl.rb +5 -3
- data/lib/gitloggl/command.rb +6 -2
- data/lib/gitloggl/commands/main.rb +3 -2
- data/lib/gitloggl/commands/manage_integration.rb +76 -0
- data/lib/gitloggl/commands/sync.rb +51 -30
- data/lib/gitloggl/commands/update.rb +49 -0
- data/lib/gitloggl/const.rb +10 -4
- data/lib/gitloggl/gitlab/cli.rb +1 -10
- data/lib/gitloggl/gitlab/issue.rb +2 -2
- data/lib/gitloggl/toggle/cli.rb +17 -24
- data/lib/gitloggl/version.rb +3 -1
- metadata +18 -5
- data/lib/gitloggl/commands/gitlab_cfg.rb +0 -50
- data/lib/gitloggl/commands/toggl_cfg.rb +0 -53
- data/lib/gitloggl/gitlab/stack/group_agg.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80535fcd6dd3199ecf83bce88b0583076823114532ca19671bf65c405eb83856
|
4
|
+
data.tar.gz: 22628ad4f9a099d2fb138eff26d31ce7104e3125a0cc1f18e5029bca5b43ca44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35d4115c1a5b2bd5e6ac1c1d62f1b8c8debc1d5be6304af027e2597c26c5edf434d7787483a5f78c75cb941de3d68cbd31b481b7f2cd5de7180f314cdc66f091
|
7
|
+
data.tar.gz: 8676f3ab7f73bb51dc318b5e51995b2777735313b17ede0ff724a9994350bdc2360099aea6c4e3f9136c0769f34834625d9d7657abd8774fe647081da267ff17
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gitloggl (0.
|
4
|
+
gitloggl (0.2)
|
5
5
|
activesupport
|
6
6
|
chronic_duration
|
7
7
|
faraday
|
@@ -15,6 +15,7 @@ PATH
|
|
15
15
|
tty-config
|
16
16
|
tty-progressbar
|
17
17
|
tty-prompt
|
18
|
+
tty-spinner
|
18
19
|
tty-table
|
19
20
|
typhoeus
|
20
21
|
|
@@ -98,6 +99,8 @@ GEM
|
|
98
99
|
tty-screen (~> 0.6.4)
|
99
100
|
wisper (~> 2.0.0)
|
100
101
|
tty-screen (0.6.5)
|
102
|
+
tty-spinner (0.9.0)
|
103
|
+
tty-cursor (~> 0.6.0)
|
101
104
|
tty-table (0.10.0)
|
102
105
|
equatable (~> 0.5.0)
|
103
106
|
necromancer (~> 0.4.0)
|
data/bin/console
CHANGED
data/gitloggl.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_dependency 'tty-progressbar'
|
30
30
|
spec.add_dependency 'tty-prompt'
|
31
31
|
spec.add_dependency 'tty-table'
|
32
|
+
spec.add_dependency 'tty-spinner'
|
32
33
|
spec.add_dependency 'pastel'
|
33
34
|
spec.add_dependency 'thor'
|
34
35
|
spec.add_dependency 'activesupport'
|
data/lib/gitloggl.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'tty-table'
|
2
2
|
require 'tty-progressbar'
|
3
|
+
require 'tty-spinner'
|
4
|
+
require 'tty-command'
|
3
5
|
require 'ostruct'
|
4
6
|
require 'faraday'
|
5
7
|
require 'faraday_middleware'
|
@@ -15,6 +17,7 @@ require 'active_support/core_ext/module/delegation'
|
|
15
17
|
require 'active_support/duration'
|
16
18
|
require 'active_support/core_ext/date'
|
17
19
|
require 'active_support/core_ext/numeric/time'
|
20
|
+
require 'active_support/core_ext/array/grouping'
|
18
21
|
require 'gitloggl/const'
|
19
22
|
require 'gitloggl/version'
|
20
23
|
require 'gitloggl/cli'
|
@@ -27,9 +30,9 @@ module Gitloggl
|
|
27
30
|
extend ActiveSupport::Autoload
|
28
31
|
|
29
32
|
autoload :Main
|
30
|
-
autoload :
|
31
|
-
autoload :GitlabCfg
|
33
|
+
autoload :ManageIntegration
|
32
34
|
autoload :Sync
|
35
|
+
autoload :Update
|
33
36
|
end
|
34
37
|
|
35
38
|
module Toggle
|
@@ -49,7 +52,6 @@ module Gitloggl
|
|
49
52
|
|
50
53
|
autoload :Abstract
|
51
54
|
autoload :Filter
|
52
|
-
autoload :GroupAgg
|
53
55
|
autoload :DetectProject
|
54
56
|
autoload :LoadNotes
|
55
57
|
autoload :UpdateSpent
|
data/lib/gitloggl/command.rb
CHANGED
@@ -24,10 +24,10 @@ module Gitloggl
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def capture_back
|
27
|
-
-> { self.class.new.execute }
|
27
|
+
-> { self.class.new(options).execute }
|
28
28
|
end
|
29
29
|
|
30
|
-
def menu_back(menu)
|
30
|
+
def menu_back(menu, back: back)
|
31
31
|
return unless back?
|
32
32
|
|
33
33
|
menu.choice 'Back', back
|
@@ -148,6 +148,10 @@ module Gitloggl
|
|
148
148
|
TTY::Which.exist?(*args)
|
149
149
|
end
|
150
150
|
|
151
|
+
def render_table(table)
|
152
|
+
table.render :unicode, padding: 1
|
153
|
+
end
|
154
|
+
|
151
155
|
def pastel(opts = {})
|
152
156
|
Pastel.new(opts)
|
153
157
|
end
|
@@ -5,9 +5,10 @@ module Gitloggl
|
|
5
5
|
class Main < Gitloggl::Command
|
6
6
|
def execute(*)
|
7
7
|
action = prompt.select('') do |menu|
|
8
|
+
menu.enum ')'
|
8
9
|
menu.choice 'SYNC', Sync
|
9
|
-
menu.choice '
|
10
|
-
menu.choice '
|
10
|
+
menu.choice 'Manage Integrations', ManageIntegration
|
11
|
+
menu.choice 'Check For Updates', Update
|
11
12
|
end
|
12
13
|
|
13
14
|
action.new(options) do |a|
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitloggl
|
4
|
+
module Commands
|
5
|
+
class ManageIntegration < Gitloggl::Command
|
6
|
+
def execute
|
7
|
+
puts render_table(table)
|
8
|
+
|
9
|
+
prompt.select('Manage toggle -> gitlab integrations') do |menu|
|
10
|
+
menu.enum ')'
|
11
|
+
menu_back(menu)
|
12
|
+
menu.choice 'Add', -> { add }
|
13
|
+
menu.choice 'Remove', -> { remove }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def remove
|
20
|
+
index = prompt.select('Select integration to remove') do |menu|
|
21
|
+
menu.enum ')'
|
22
|
+
|
23
|
+
integrations.each_with_index do |row, index|
|
24
|
+
menu.choice row[Const::NAME], index
|
25
|
+
end
|
26
|
+
|
27
|
+
menu_back(menu, back: -1)
|
28
|
+
end
|
29
|
+
|
30
|
+
return execute if index.negative?
|
31
|
+
|
32
|
+
integrations.delete_at(index)
|
33
|
+
config.set(Const::INTEGRATIONS, value: integrations)
|
34
|
+
config.write(force: true)
|
35
|
+
end
|
36
|
+
|
37
|
+
def add
|
38
|
+
result = prompt.collect do
|
39
|
+
key(Const::NAME).ask('Name?', default: 'Default')
|
40
|
+
key(Const::GITLAB_URL).ask('Gitlab URL?', default: 'https://gitlab.com')
|
41
|
+
key(Const::GITLAB_TOKEN).ask('Gitlab Token?', required: true)
|
42
|
+
key(Const::TOGGL_WORKSPACE_ID).ask('Toggl WorkspaceID?', required: true)
|
43
|
+
key(Const::TOGGL_PROJECT_ID).ask('Toggl ProjectID? (not required)')
|
44
|
+
key(Const::TOGGL_TOKEN).ask('Toggl Token?', requred: true)
|
45
|
+
end
|
46
|
+
|
47
|
+
config.append(result, to: Const::INTEGRATIONS)
|
48
|
+
config.write(force: true)
|
49
|
+
end
|
50
|
+
|
51
|
+
def table
|
52
|
+
table = TTY::Table.new header: ['№', 'Name', 'Gitlab URL', 'Gitlab Token', 'Toggl WorkspaceID', 'Toggle ProjectID', 'Toggl Token']
|
53
|
+
|
54
|
+
integrations(default: [{}]).each_with_index do |row, index|
|
55
|
+
table << [
|
56
|
+
index.next,
|
57
|
+
*row.values_at(
|
58
|
+
Const::NAME,
|
59
|
+
Const::GITLAB_URL,
|
60
|
+
Const::GITLAB_TOKEN,
|
61
|
+
Const::TOGGL_WORKSPACE_ID,
|
62
|
+
Const::TOGGL_PROJECT_ID,
|
63
|
+
Const::TOGGL_TOKEN
|
64
|
+
)
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
table
|
69
|
+
end
|
70
|
+
|
71
|
+
def integrations(default: [])
|
72
|
+
config.fetch(Const::INTEGRATIONS, default: default)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -3,10 +3,16 @@
|
|
3
3
|
module Gitloggl
|
4
4
|
module Commands
|
5
5
|
class Sync < Gitloggl::Command
|
6
|
-
attr_accessor :date_from, :date_to
|
6
|
+
attr_accessor :integration, :date_from, :date_to
|
7
7
|
attr_accessor :toggl_bar, :gitlab_bar
|
8
8
|
|
9
9
|
def execute
|
10
|
+
if integrations.empty?
|
11
|
+
puts pastel.yellow('Please add integration first')
|
12
|
+
return back.call
|
13
|
+
end
|
14
|
+
|
15
|
+
self.integration = select_integration
|
10
16
|
self.date_from, self.date_to = select_dates
|
11
17
|
|
12
18
|
setup_toggl_hooks
|
@@ -22,34 +28,33 @@ module Gitloggl
|
|
22
28
|
def print_tables
|
23
29
|
if updated.any?
|
24
30
|
puts pastel.green('Updated tracks')
|
25
|
-
puts(updated_table)
|
31
|
+
puts render_table(updated_table)
|
26
32
|
end
|
27
33
|
|
28
34
|
if rejected.any?
|
29
35
|
puts pastel.yellow('Rejected tracks')
|
30
|
-
puts(rejected_table)
|
36
|
+
puts render_table(rejected_table)
|
31
37
|
end
|
32
38
|
end
|
33
39
|
|
34
40
|
def setup_toggl_hooks
|
35
|
-
toggl.
|
36
|
-
self.toggl_bar = bars.register("toggl [:bar] :percent", total:
|
37
|
-
self.gitlab_bar = bars.register("gitlab [:bar] :percent", total:
|
41
|
+
toggl.on_done do |data|
|
42
|
+
self.toggl_bar = bars.register("toggl [:bar] :percent", total: data.length)
|
43
|
+
self.gitlab_bar = bars.register("gitlab [:bar] :percent", total: data.length)
|
44
|
+
toggl_bar.advance(data.length)
|
38
45
|
end
|
39
46
|
|
40
|
-
toggl.
|
41
|
-
|
42
|
-
|
47
|
+
toggl.on_done do |data|
|
48
|
+
data.in_groups_of(10, false) do |group|
|
49
|
+
group.map! do |result|
|
50
|
+
Gitlab::Issue.new(
|
51
|
+
spent_ms: Integer(result.spent_ms),
|
52
|
+
title: result.title
|
53
|
+
)
|
54
|
+
end
|
43
55
|
|
44
|
-
|
45
|
-
issues = response.body.fetch('data').map do |row|
|
46
|
-
Gitlab::Issue.new(
|
47
|
-
spent_ms: Integer(row.fetch('dur')),
|
48
|
-
description: row.fetch('description')
|
49
|
-
)
|
56
|
+
gitlab.batch(group)
|
50
57
|
end
|
51
|
-
|
52
|
-
gitlab.batch(issues)
|
53
58
|
end
|
54
59
|
end
|
55
60
|
|
@@ -58,10 +63,6 @@ module Gitloggl
|
|
58
63
|
gitlab_bar.advance
|
59
64
|
end
|
60
65
|
|
61
|
-
gitlab.on_skipped do
|
62
|
-
gitlab_bar.advance
|
63
|
-
end
|
64
|
-
|
65
66
|
gitlab.on_rejected do |issue, reason|
|
66
67
|
rejected.push([issue, reason])
|
67
68
|
end
|
@@ -82,21 +83,25 @@ module Gitloggl
|
|
82
83
|
def rejected_table
|
83
84
|
table = TTY::Table.new header: %w[Track Reason]
|
84
85
|
|
85
|
-
rejected.uniq { |(i)| i.
|
86
|
-
table << [issue.
|
86
|
+
rejected.uniq { |(i, _)| i.title }.each do |(issue, reason)|
|
87
|
+
table << [issue.title, reason]
|
87
88
|
end
|
88
89
|
|
89
|
-
table
|
90
|
+
table
|
90
91
|
end
|
91
92
|
|
92
93
|
def updated_table
|
93
94
|
table = TTY::Table.new header: %w[Track Diff]
|
94
95
|
|
96
|
+
updated.sort_by! do |(_, diff)|
|
97
|
+
-diff
|
98
|
+
end
|
99
|
+
|
95
100
|
updated.each do |(issue, diff)|
|
96
|
-
table << [issue.
|
101
|
+
table << [issue.title, %{added +#{ChronicDuration.output(diff, keep_zero: true)}}]
|
97
102
|
end
|
98
103
|
|
99
|
-
table
|
104
|
+
table
|
100
105
|
end
|
101
106
|
|
102
107
|
def bars
|
@@ -106,8 +111,9 @@ module Gitloggl
|
|
106
111
|
def toggl
|
107
112
|
@toggl ||= Toggle::Cli.new do |c|
|
108
113
|
c.verbose = verbose?
|
109
|
-
c.
|
110
|
-
c.
|
114
|
+
c.project_id = integration.fetch(Const::TOGGL_PROJECT_ID)
|
115
|
+
c.workspace_id = integration.fetch(Const::TOGGL_WORKSPACE_ID)
|
116
|
+
c.token = integration.fetch(Const::TOGGL_TOKEN)
|
111
117
|
c.date_from = date_from
|
112
118
|
c.date_to = date_to
|
113
119
|
end
|
@@ -116,18 +122,33 @@ module Gitloggl
|
|
116
122
|
def gitlab
|
117
123
|
@gitlab ||= Gitlab::Cli.new do |c|
|
118
124
|
c.verbose = verbose?
|
119
|
-
c.url =
|
120
|
-
c.token =
|
125
|
+
c.url = integration.fetch(Const::GITLAB_URL)
|
126
|
+
c.token = integration.fetch(Const::GITLAB_TOKEN)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def select_integration
|
131
|
+
prompt.select('Select integration') do |menu|
|
132
|
+
menu.enum ')'
|
133
|
+
|
134
|
+
integrations.each do |row|
|
135
|
+
menu.choice row[Const::NAME], row
|
136
|
+
end
|
121
137
|
end
|
122
138
|
end
|
123
139
|
|
124
140
|
def select_dates
|
125
141
|
prompt.select('Select period for sync. Tracks will be added to gitlab if diff will be detected') do |menu|
|
142
|
+
menu.enum ')'
|
126
143
|
menu.choice 'Past 3 weeks', [3.weeks.ago.to_date, Date.current]
|
127
144
|
menu.choice 'Past 2 weeks', [2.weeks.ago.to_date, Date.current]
|
128
145
|
menu.choice 'Past 7 days', [7.days.ago.to_date, Date.current]
|
129
146
|
end
|
130
147
|
end
|
148
|
+
|
149
|
+
def integrations
|
150
|
+
config.fetch(Const::INTEGRATIONS, default: [])
|
151
|
+
end
|
131
152
|
end
|
132
153
|
end
|
133
154
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitloggl
|
4
|
+
module Commands
|
5
|
+
class Update < Gitloggl::Command
|
6
|
+
RUBYGEMS_URL = 'https://rubygems.org/api/v1/gems/gitloggl.json'
|
7
|
+
|
8
|
+
def execute
|
9
|
+
spinner = TTY::Spinner.new("[:spinner] Loading ...", format: :pulse_2)
|
10
|
+
outdated = outdated?(parse_version(VERSION), parse_version(remote_version))
|
11
|
+
spinner.stop
|
12
|
+
|
13
|
+
unless outdated
|
14
|
+
puts pastel.yellow('No Updates Available')
|
15
|
+
return back.call
|
16
|
+
end
|
17
|
+
|
18
|
+
select_update
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def select_update
|
24
|
+
yes = prompt.yes?("#{remote_version} version available, update?")
|
25
|
+
|
26
|
+
return back.call unless yes
|
27
|
+
|
28
|
+
cmd = TTY::Command.new
|
29
|
+
cmd.run('gem update gitloggl')
|
30
|
+
end
|
31
|
+
|
32
|
+
def outdated?(current, remote)
|
33
|
+
remote.each_with_index do |num, ix|
|
34
|
+
return true if num > current[ix].to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def remote_version
|
41
|
+
@remote_version ||= Connection.new(RUBYGEMS_URL).get.body.fetch('version')
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_version(string)
|
45
|
+
string.split('.').map(&:to_i)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/gitloggl/const.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gitloggl
|
2
4
|
module Const
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
INTEGRATIONS = :integrations
|
6
|
+
|
7
|
+
NAME = 'name'
|
8
|
+
GITLAB_URL = 'gitlab_url'
|
9
|
+
GITLAB_TOKEN = 'gitlab_token'
|
10
|
+
TOGGL_WORKSPACE_ID = 'toggl_workspace_id'
|
11
|
+
TOGGL_PROJECT_ID = 'toggl_project_id'
|
12
|
+
TOGGL_TOKEN = 'toggl_token'
|
7
13
|
end
|
8
14
|
end
|
data/lib/gitloggl/gitlab/cli.rb
CHANGED
@@ -7,7 +7,6 @@ module Gitloggl
|
|
7
7
|
define_hook :on_rejected, scope: ->(*) { nil }
|
8
8
|
define_hook :on_updated, scope: ->(*) { nil }
|
9
9
|
define_hook :on_completed, scope: ->(*) { nil }
|
10
|
-
define_hook :on_skipped, scope: ->(*) { nil }
|
11
10
|
|
12
11
|
attr_accessor :token, :url, :verbose
|
13
12
|
|
@@ -26,10 +25,6 @@ module Gitloggl
|
|
26
25
|
false
|
27
26
|
end
|
28
27
|
|
29
|
-
b.use Stack::GroupAgg, callback: ->(issues) do
|
30
|
-
issues.each { skipped }
|
31
|
-
end
|
32
|
-
|
33
28
|
b.use Stack::DetectProject
|
34
29
|
|
35
30
|
b.use Stack::Filter, where: -> (issue) do
|
@@ -43,7 +38,7 @@ module Gitloggl
|
|
43
38
|
b.use Stack::LoadNotes
|
44
39
|
|
45
40
|
b.use Stack::UpdateSpent, callback: ->(issue, diff_sec) do
|
46
|
-
updated(issue,
|
41
|
+
updated(issue, diff_sec)
|
47
42
|
end
|
48
43
|
end
|
49
44
|
|
@@ -62,10 +57,6 @@ module Gitloggl
|
|
62
57
|
run_hook(:on_updated, issue, diff)
|
63
58
|
end
|
64
59
|
|
65
|
-
def skipped
|
66
|
-
run_hook(:on_skipped)
|
67
|
-
end
|
68
|
-
|
69
60
|
def connection
|
70
61
|
@connection ||= Connection.new(url, headers: { 'PRIVATE-TOKEN' => token }, verbose: verbose).tap do |c|
|
71
62
|
c.transport.basic_auth(token, 'api_token')
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Gitloggl
|
2
2
|
module Gitlab
|
3
|
-
class Issue < Struct.new(:
|
3
|
+
class Issue < Struct.new(:title, :project_id, :spent_ms, keyword_init: true)
|
4
4
|
ISSUE_PATH_RE = /([[[:alnum:]]_-]*)#(\d+)/ # "poslogic-partner#471"
|
5
5
|
|
6
6
|
attr_accessor :notes
|
@@ -10,7 +10,7 @@ module Gitloggl
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def path
|
13
|
-
return nil unless
|
13
|
+
return nil unless title =~ ISSUE_PATH_RE
|
14
14
|
return nil unless $1.present? && $2.present?
|
15
15
|
|
16
16
|
@path ||= OpenStruct.new(project_path: $1, issue_id: $2)
|
data/lib/gitloggl/toggle/cli.rb
CHANGED
@@ -4,54 +4,47 @@ module Gitloggl
|
|
4
4
|
include Hooks
|
5
5
|
include Hooks::InstanceHooks
|
6
6
|
|
7
|
-
define_hook :
|
8
|
-
define_hook :on_each_page, scope: ->(*) { nil }
|
7
|
+
define_hook :on_done, scope: ->(*) { nil }
|
9
8
|
|
10
|
-
attr_accessor :token, :workspace_id, :date_from, :date_to, :verbose
|
9
|
+
attr_accessor :token, :workspace_id, :project_id, :date_from, :date_to, :verbose
|
11
10
|
|
12
11
|
def initialize(params = {})
|
13
12
|
params.each { |k, v| public_send("#{k}=", v) }
|
14
13
|
yield(self) if block_given?
|
15
14
|
end
|
16
15
|
|
17
|
-
def run
|
18
|
-
|
16
|
+
def run
|
17
|
+
data = request.fetch('data').flat_map { |row| row.fetch('items') }
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
per_page: per_page,
|
27
|
-
total_pages: total_pages,
|
28
|
-
page: page,
|
29
|
-
body: body
|
30
|
-
)
|
31
|
-
|
32
|
-
run_hook(:on_first_page, result) if page == 1
|
33
|
-
run_hook(:on_each_page, result)
|
19
|
+
data.map! do |row|
|
20
|
+
OpenStruct.new(
|
21
|
+
title: row.fetch('title').fetch('time_entry'),
|
22
|
+
spent_ms: row.fetch('time')
|
23
|
+
)
|
24
|
+
end
|
34
25
|
|
35
|
-
|
26
|
+
run_hook(:on_done, data)
|
36
27
|
end
|
37
28
|
|
38
29
|
private
|
39
30
|
|
40
31
|
# @return [JSON]
|
41
|
-
def request
|
42
|
-
response = connection.get('/reports/api/v2/
|
32
|
+
def request
|
33
|
+
response = connection.get('/reports/api/v2/summary', {
|
43
34
|
workspace_id: workspace_id,
|
35
|
+
project_ids: project_id,
|
44
36
|
since: date_from,
|
45
37
|
until: date_to,
|
38
|
+
grouping: 'projects',
|
39
|
+
subgrouping: 'time_entries',
|
46
40
|
user_agent: Connection::USER_AGENT,
|
47
|
-
page: page
|
48
41
|
})
|
49
42
|
|
50
43
|
response.body
|
51
44
|
end
|
52
45
|
|
53
46
|
def connection
|
54
|
-
@connection ||= Connection.new('https://toggl.com
|
47
|
+
@connection ||= Connection.new('https://toggl.com', verbose: verbose).tap do |c|
|
55
48
|
c.transport.basic_auth(token, 'api_token')
|
56
49
|
end
|
57
50
|
end
|
data/lib/gitloggl/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitloggl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shylau Aloaksandr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-02-
|
11
|
+
date: 2019-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tty-color
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: tty-spinner
|
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'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: pastel
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -298,10 +312,10 @@ files:
|
|
298
312
|
- lib/gitloggl.rb
|
299
313
|
- lib/gitloggl/cli.rb
|
300
314
|
- lib/gitloggl/command.rb
|
301
|
-
- lib/gitloggl/commands/gitlab_cfg.rb
|
302
315
|
- lib/gitloggl/commands/main.rb
|
316
|
+
- lib/gitloggl/commands/manage_integration.rb
|
303
317
|
- lib/gitloggl/commands/sync.rb
|
304
|
-
- lib/gitloggl/commands/
|
318
|
+
- lib/gitloggl/commands/update.rb
|
305
319
|
- lib/gitloggl/connection.rb
|
306
320
|
- lib/gitloggl/const.rb
|
307
321
|
- lib/gitloggl/gitlab/cli.rb
|
@@ -309,7 +323,6 @@ files:
|
|
309
323
|
- lib/gitloggl/gitlab/stack/abstract.rb
|
310
324
|
- lib/gitloggl/gitlab/stack/detect_project.rb
|
311
325
|
- lib/gitloggl/gitlab/stack/filter.rb
|
312
|
-
- lib/gitloggl/gitlab/stack/group_agg.rb
|
313
326
|
- lib/gitloggl/gitlab/stack/load_notes.rb
|
314
327
|
- lib/gitloggl/gitlab/stack/update_spent.rb
|
315
328
|
- lib/gitloggl/templates/.gitkeep
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gitloggl
|
4
|
-
module Commands
|
5
|
-
class GitlabCfg < Gitloggl::Command
|
6
|
-
def execute(*)
|
7
|
-
render_config_table
|
8
|
-
|
9
|
-
prompt.select('') do |menu|
|
10
|
-
menu.choice 'Back', back if back?
|
11
|
-
menu.choice 'Add site', -> { add_site }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def add_site
|
18
|
-
domain = ask_domain
|
19
|
-
token = ask_token
|
20
|
-
|
21
|
-
return unless prompt.yes?("Change settings? Domain: #{pastel.green(domain)}, token: #{pastel.green(token)}")
|
22
|
-
|
23
|
-
config.set(Const::GITLAB_URL, value: domain)
|
24
|
-
config.set(Const::GITLAB_TOKEN, value: token)
|
25
|
-
|
26
|
-
config.write(force: true)
|
27
|
-
end
|
28
|
-
|
29
|
-
def ask_domain
|
30
|
-
prompt.ask('Enter gitlab domain:', default: 'https://gitlab.com') do |q|
|
31
|
-
q.required true
|
32
|
-
q.validate /\A.+\Z/
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def ask_token
|
37
|
-
prompt.ask('Enter access token') do |q|
|
38
|
-
q.required true
|
39
|
-
q.validate /\A.+\Z/
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def render_config_table
|
44
|
-
table = TTY::Table.new header: %w[Domain Token]
|
45
|
-
table << [config.fetch(Const::GITLAB_URL), config.fetch(Const::GITLAB_TOKEN)]
|
46
|
-
puts table.render :unicode, padding: 1
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gitloggl
|
4
|
-
module Commands
|
5
|
-
class TogglCfg < Gitloggl::Command
|
6
|
-
def execute(*)
|
7
|
-
render_config_config
|
8
|
-
|
9
|
-
prompt.select('') do |menu|
|
10
|
-
menu.enum ')'
|
11
|
-
menu_back(menu)
|
12
|
-
menu.choice 'Change', -> { change }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def change
|
19
|
-
workspace_id = ask_workspace_id
|
20
|
-
token = ask_token
|
21
|
-
|
22
|
-
return unless prompt.yes? <<~ECHO
|
23
|
-
Change settings? WorkspaceID: #{pastel.green(workspace_id)}, token: #{pastel.green(token)}
|
24
|
-
ECHO
|
25
|
-
|
26
|
-
config.set(Const::TOGGL_WORKSPACE_ID, value: workspace_id)
|
27
|
-
config.set(Const::TOGGL_TOKEN, value: token)
|
28
|
-
|
29
|
-
config.write(force: true)
|
30
|
-
end
|
31
|
-
|
32
|
-
def ask_workspace_id
|
33
|
-
prompt.ask('Enter workspaceID:') do |q|
|
34
|
-
q.required true
|
35
|
-
q.validate /\A.+\Z/
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def ask_token
|
40
|
-
prompt.ask('Enter token:') do |q|
|
41
|
-
q.required true
|
42
|
-
q.validate /\A.+\Z/
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def render_config_config
|
47
|
-
table = TTY::Table.new header: %w[WorkspaceID Token]
|
48
|
-
table << [config.fetch(Const::TOGGL_WORKSPACE_ID), config.fetch(Const::TOGGL_TOKEN)]
|
49
|
-
puts table.render :unicode, padding: 1
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gitloggl
|
4
|
-
module Gitlab
|
5
|
-
module Stack
|
6
|
-
class GroupAgg < Abstract
|
7
|
-
opt :callback
|
8
|
-
|
9
|
-
def before_call
|
10
|
-
env.issues = env.issues.group_by(&:path).each_with_object([]) do |(_, group), object|
|
11
|
-
object.push(group.inject { |a, b| a + b })
|
12
|
-
|
13
|
-
next unless group.many?
|
14
|
-
|
15
|
-
callback!.call(group[1..-1])
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|