abt-cli 0.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 +7 -0
- data/bin/abt +14 -0
- data/lib/abt.rb +5 -0
- data/lib/abt/asana_client.rb +53 -0
- data/lib/abt/cli.rb +103 -0
- data/lib/abt/cli/dialogs.rb +67 -0
- data/lib/abt/git_config.rb +78 -0
- data/lib/abt/harvest_client.rb +58 -0
- data/lib/abt/help.rb +56 -0
- data/lib/abt/help/cli.rb +59 -0
- data/lib/abt/help/markdown.rb +66 -0
- data/lib/abt/http_error.rb +45 -0
- data/lib/abt/providers.rb +5 -0
- data/lib/abt/providers/asana.rb +60 -0
- data/lib/abt/providers/asana/base_command.rb +62 -0
- data/lib/abt/providers/asana/clear.rb +24 -0
- data/lib/abt/providers/asana/clear_global.rb +24 -0
- data/lib/abt/providers/asana/current.rb +69 -0
- data/lib/abt/providers/asana/harvest_link_entry_data.rb +48 -0
- data/lib/abt/providers/asana/init.rb +62 -0
- data/lib/abt/providers/asana/move.rb +54 -0
- data/lib/abt/providers/asana/pick_task.rb +46 -0
- data/lib/abt/providers/asana/projects.rb +30 -0
- data/lib/abt/providers/asana/start.rb +22 -0
- data/lib/abt/providers/asana/tasks.rb +35 -0
- data/lib/abt/providers/harvest.rb +52 -0
- data/lib/abt/providers/harvest/base_command.rb +70 -0
- data/lib/abt/providers/harvest/clear.rb +24 -0
- data/lib/abt/providers/harvest/clear_global.rb +24 -0
- data/lib/abt/providers/harvest/current.rb +79 -0
- data/lib/abt/providers/harvest/init.rb +61 -0
- data/lib/abt/providers/harvest/pick_task.rb +45 -0
- data/lib/abt/providers/harvest/projects.rb +29 -0
- data/lib/abt/providers/harvest/start.rb +58 -0
- data/lib/abt/providers/harvest/stop.rb +51 -0
- data/lib/abt/providers/harvest/tasks.rb +36 -0
- data/lib/abt/version.rb +5 -0
- metadata +138 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Abt
|
4
|
+
module Providers
|
5
|
+
class Harvest
|
6
|
+
class Init < BaseCommand
|
7
|
+
def self.command
|
8
|
+
'init harvest'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.description
|
12
|
+
'Pick Harvest project for current git repository'
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
warn 'Loading projects'
|
17
|
+
|
18
|
+
projects # Load projects up front to make it obvious that searches are instant
|
19
|
+
project = find_search_result
|
20
|
+
|
21
|
+
remember_project_id(project['id'])
|
22
|
+
remember_task_id(nil)
|
23
|
+
|
24
|
+
print_project(project)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def find_search_result
|
30
|
+
loop do
|
31
|
+
matches = matches_for_string cli.prompt('Enter search')
|
32
|
+
if matches.empty?
|
33
|
+
warn 'No matches'
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
warn 'Showing the 10 first matches' if matches.size > 10
|
38
|
+
choice = cli.prompt_choice 'Select a project', matches[0...10], true
|
39
|
+
break choice unless choice.nil?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def matches_for_string(string)
|
44
|
+
search_string = sanitize_string(string)
|
45
|
+
|
46
|
+
projects.select do |project|
|
47
|
+
sanitize_string(project['name']).include?(search_string)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def sanitize_string(string)
|
52
|
+
string.downcase.gsub(/[^\w]/, '')
|
53
|
+
end
|
54
|
+
|
55
|
+
def projects
|
56
|
+
@projects ||= Harvest.client.get_paged('projects')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Abt
|
4
|
+
module Providers
|
5
|
+
class Harvest
|
6
|
+
class PickTask < BaseCommand
|
7
|
+
def self.command
|
8
|
+
'pick-task harvest[:<project-id>]'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.description
|
12
|
+
'Pick task for current git repository'
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
warn project['name']
|
17
|
+
task = cli.prompt_choice 'Select a task', tasks
|
18
|
+
|
19
|
+
remember_project_id(project_id) # We might have gotten the project ID as an argument
|
20
|
+
remember_task_id(task['id'])
|
21
|
+
|
22
|
+
print_task(project, task)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def project
|
28
|
+
@project ||= Harvest.client.get("projects/#{project_id}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def tasks
|
32
|
+
project_task_assignments.map { |assignment| assignment['task'] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def project_task_assignments
|
36
|
+
@project_task_assignments ||= begin
|
37
|
+
Harvest.client.get_paged("projects/#{project_id}/task_assignments", is_active: true)
|
38
|
+
rescue Abt::HttpError::HttpError # rubocop:disable Layout/RescueEnsureAlignment
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Abt
|
4
|
+
module Providers
|
5
|
+
class Harvest
|
6
|
+
class Projects < BaseCommand
|
7
|
+
def self.command
|
8
|
+
'projects harvest'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.description
|
12
|
+
'List all available projects - useful for piping into grep etc.'
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
projects.map do |project|
|
17
|
+
print_project(project)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def projects
|
24
|
+
@projects ||= Harvest.client.get_paged('projects', is_active: true)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Abt
|
4
|
+
module Providers
|
5
|
+
class Harvest
|
6
|
+
class Start < BaseCommand
|
7
|
+
def self.command
|
8
|
+
'start harvest[:<project-id>/<task-id>]'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.description
|
12
|
+
'Start tracker for current or specified task. Add a relevant provider to link the time entry: E.g. `abt start harvest asana`' # rubocop:disable Layout/LineLength
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
Current.new(arg_str: arg_str, cli: cli).call unless arg_str.nil?
|
17
|
+
|
18
|
+
abort('No task selected') if task_id.nil?
|
19
|
+
|
20
|
+
create_time_entry
|
21
|
+
|
22
|
+
warn 'Tracker successfully started'
|
23
|
+
rescue Abt::HttpError::HttpError => e
|
24
|
+
warn e
|
25
|
+
abort 'Unable to start tracker'
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def create_time_entry
|
31
|
+
body = Oj.dump({
|
32
|
+
project_id: Abt::GitConfig.local('abt.harvest.projectId'),
|
33
|
+
task_id: Abt::GitConfig.local('abt.harvest.taskId'),
|
34
|
+
user_id: Harvest.user_id,
|
35
|
+
spent_date: Date.today.iso8601
|
36
|
+
}.merge(external_link_data), mode: :json)
|
37
|
+
Harvest.client.post('time_entries', body)
|
38
|
+
end
|
39
|
+
|
40
|
+
def external_link_data
|
41
|
+
@external_link_data ||= begin
|
42
|
+
arg_strs = cli.args.join(' ')
|
43
|
+
lines = `#{$PROGRAM_NAME} harvest-time-entry-data #{arg_strs}`.split("\n")
|
44
|
+
|
45
|
+
return {} if lines.empty?
|
46
|
+
|
47
|
+
# TODO: Make user choose which reference to use by printing the urls
|
48
|
+
if lines.length > 1
|
49
|
+
abort 'Multiple providers had harvest reference data, only one is supported at a time'
|
50
|
+
end
|
51
|
+
|
52
|
+
Oj.load(lines.first)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Abt
|
4
|
+
module Providers
|
5
|
+
class Harvest
|
6
|
+
class Stop < BaseCommand
|
7
|
+
def self.command
|
8
|
+
'stop harvest'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.description
|
12
|
+
'Stop running harvest tracker'
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
abort 'No running time entry' if time_entry.nil?
|
17
|
+
|
18
|
+
Harvest.client.patch("time_entries/#{time_entry['id']}/stop")
|
19
|
+
warn 'Harvest time entry stopped'
|
20
|
+
print_task(project, task)
|
21
|
+
rescue Abt::HttpError::HttpError => e
|
22
|
+
warn e
|
23
|
+
abort 'Unable to stop time entry'
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def project
|
29
|
+
time_entry['project']
|
30
|
+
end
|
31
|
+
|
32
|
+
def task
|
33
|
+
time_entry['task']
|
34
|
+
end
|
35
|
+
|
36
|
+
def time_entry
|
37
|
+
@time_entry ||= begin
|
38
|
+
Harvest.client.get_paged(
|
39
|
+
'time_entries',
|
40
|
+
is_running: true,
|
41
|
+
user_id: Harvest.user_id
|
42
|
+
).first
|
43
|
+
rescue Abt::HttpError::HttpError => e # rubocop:disable Layout/RescueEnsureAlignment
|
44
|
+
warn e
|
45
|
+
abort 'Unable to fetch running time entry'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Abt
|
4
|
+
module Providers
|
5
|
+
class Harvest
|
6
|
+
class Tasks < BaseCommand
|
7
|
+
def self.command
|
8
|
+
'tasks harvest'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.description
|
12
|
+
'List available tasks on project - useful for piping into grep etc.'
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
project_task_assignments.each do |a|
|
17
|
+
project = a['project']
|
18
|
+
task = a['task']
|
19
|
+
|
20
|
+
print_task(project, task)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def project_task_assignments
|
27
|
+
@project_task_assignments ||= begin
|
28
|
+
Harvest.client.get_paged("projects/#{project_id}/task_assignments", is_active: true)
|
29
|
+
rescue Abt::HttpError::HttpError # rubocop:disable Layout/RescueEnsureAlignment
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/abt/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abt-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jesper Sørensen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-01-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-inflector
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: oj
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.10'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- js@abtion.com
|
72
|
+
executables:
|
73
|
+
- abt
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- "./lib/abt.rb"
|
78
|
+
- "./lib/abt/asana_client.rb"
|
79
|
+
- "./lib/abt/cli.rb"
|
80
|
+
- "./lib/abt/cli/dialogs.rb"
|
81
|
+
- "./lib/abt/git_config.rb"
|
82
|
+
- "./lib/abt/harvest_client.rb"
|
83
|
+
- "./lib/abt/help.rb"
|
84
|
+
- "./lib/abt/help/cli.rb"
|
85
|
+
- "./lib/abt/help/markdown.rb"
|
86
|
+
- "./lib/abt/http_error.rb"
|
87
|
+
- "./lib/abt/providers.rb"
|
88
|
+
- "./lib/abt/providers/asana.rb"
|
89
|
+
- "./lib/abt/providers/asana/base_command.rb"
|
90
|
+
- "./lib/abt/providers/asana/clear.rb"
|
91
|
+
- "./lib/abt/providers/asana/clear_global.rb"
|
92
|
+
- "./lib/abt/providers/asana/current.rb"
|
93
|
+
- "./lib/abt/providers/asana/harvest_link_entry_data.rb"
|
94
|
+
- "./lib/abt/providers/asana/init.rb"
|
95
|
+
- "./lib/abt/providers/asana/move.rb"
|
96
|
+
- "./lib/abt/providers/asana/pick_task.rb"
|
97
|
+
- "./lib/abt/providers/asana/projects.rb"
|
98
|
+
- "./lib/abt/providers/asana/start.rb"
|
99
|
+
- "./lib/abt/providers/asana/tasks.rb"
|
100
|
+
- "./lib/abt/providers/harvest.rb"
|
101
|
+
- "./lib/abt/providers/harvest/base_command.rb"
|
102
|
+
- "./lib/abt/providers/harvest/clear.rb"
|
103
|
+
- "./lib/abt/providers/harvest/clear_global.rb"
|
104
|
+
- "./lib/abt/providers/harvest/current.rb"
|
105
|
+
- "./lib/abt/providers/harvest/init.rb"
|
106
|
+
- "./lib/abt/providers/harvest/pick_task.rb"
|
107
|
+
- "./lib/abt/providers/harvest/projects.rb"
|
108
|
+
- "./lib/abt/providers/harvest/start.rb"
|
109
|
+
- "./lib/abt/providers/harvest/stop.rb"
|
110
|
+
- "./lib/abt/providers/harvest/tasks.rb"
|
111
|
+
- "./lib/abt/version.rb"
|
112
|
+
- bin/abt
|
113
|
+
homepage: https://github.com/abtion/abt
|
114
|
+
licenses:
|
115
|
+
- MIT
|
116
|
+
metadata:
|
117
|
+
homepage_uri: https://github.com/abtion/abt
|
118
|
+
source_code_uri: https://github.com/abtion/abt
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubygems_version: 3.0.3
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: Versatile scripts
|
138
|
+
test_files: []
|